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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b25b4f9bf189bb33a19980c2cd6247a93ae2dd14df820eaa9e991425fa56b0dd
4
- data.tar.gz: '0646683a124670135b38f5d93667cac8140a96d74c352d6bb28483cec93e3ee8'
3
+ metadata.gz: 146c2bdc6330d735c979a82c0d83fc1351ad486a49e4e66b833d12adde1a5cd4
4
+ data.tar.gz: b45b7ecef617e60aea43f621914653dd0c027710d6f563a401eea5e88b670cf6
5
5
  SHA512:
6
- metadata.gz: 0dc8fdc7c0b9c4181ed50372eeebc41d75bccaf4c81db63a79da218918c0c71d70fd0fa9e6df9e8f6e46d52c4153b0934577a76fbdc03d90e23d28bda6a37811
7
- data.tar.gz: c65b56bef0deb983be7cd81e914834de1536c07633c3709a642eedf2d3b461344d4a2ddfc0beae0f85ac0a954cf895472459919b2cf317ea2f26b633309a1f1a
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 1-5" if opts[:margin] < 1 || opts[:margin] > 5
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
@@ -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
- # content = content.strip
27
- if /\A.+\^\z/ =~ content.strip
28
- @content = content.gsub("^"){""}.strip # The actual element content
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
@@ -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(e.content, @font, @font_size) + @font_size
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(e.content, @font, @font_size) + @font_size
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 = false)
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 /[\n\r]/
175
- gottoken = false # same as do nothing
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 = "sans-serif"
29
- when /(?:serif|math)/
30
- @fontstyle = "serif"
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
- super(e_list, metrics, symmetrize, color, leafstyle, multibyte, @font, @font_size)
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: FONT_SIZEpx; ST; WA;' x='X_VALUE' y='Y_VALUE' TD font-family='#{@fontstyle}'>CONTENT</text>\n"
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="#{@width}" height="#{@height}" version="1.1" xmlns="http://www.w3.org/2000/svg">
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
- header + @tree_data + footer
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 = img_get_txt_width(main, @font, @font_size)
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
- txt_width = main_width + sub_width
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] * 1.5
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
- sub_data = @text_styles.sub(/COLOR/, col)
205
- sub_data = sub_data.sub(/FONT_SIZE/, @sub_size.to_s)
206
- sub_x = main_x + main_width
207
- sub_y = top + (@e_height - @m[:e_padd] + @sub_size / 10)
208
- if (sub.length > 0 )
209
- sub_data = sub_data.sub(/X_VALUE/, sub_x.ceil.to_s)
210
- sub_data = sub_data.sub(/Y_VALUE/, sub_y.ceil.to_s)
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/, sub)
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.ceil.to_s)
231
- line_data = line_data.sub(/Y1/, fromTop.ceil.to_s)
232
- line_data = line_data.sub(/X2/, toLeft.ceil.to_s)
233
- @tree_data += line_data.sub(/Y2/, toBot.ceil.to_s)
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).ceil
247
- fromLeft1 = (fromCenter + textW / 2).ceil
248
- fromLeft2 = (fromCenter - textW / 2).ceil
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.ceil.to_s)
258
- polygon_data = polygon_data.sub(/Y1/, fromTop.ceil.to_s)
259
- polygon_data = polygon_data.sub(/X2/, fromLeft2.ceil.to_s)
260
- polygon_data = polygon_data.sub(/Y2/, fromTop.ceil.to_s)
261
- polygon_data = polygon_data.sub(/X3/, toLeft.ceil.to_s)
262
- @tree_data += polygon_data.sub(/Y3/, toBot.ceil.to_s)
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 = false)
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
- # if(sub.contains_cjk?)
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 = 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
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
- @im.interlace = PlaneInterlace
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
- @im.border!(@margin, @margin, "white")
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
- main_width = img_get_txt_width(main, main_font, @font_size)
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
- txt_width = main_width + sub_width
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
- main_x = txt_pos
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
- @gc.text(main_x.ceil, main_y.ceil, main)
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.length > 0 )
236
+ if (sub != "" )
213
237
  @gc.pointsize(@sub_size)
214
- sub_x = txt_pos + main_width + @sub_space_width
215
- sub_y = top + (@e_height - @m[:e_padd] + @sub_size / 2)
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.text(sub_x.ceil, sub_y.ceil, sub)
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 = false)
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]
@@ -1,4 +1,4 @@
1
1
  module RSyntaxTree
2
- VERSION = "0.8.6"
2
+ VERSION = "0.9.3"
3
3
  end
4
4
 
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 = CGI.unescape(value)
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 + "/NotoSansCJKjp-Regular.otf"
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 + "/NotoSerifCJKjp-Regular.otf"
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 + "/NotoSerifCJKjp-Regular.otf"
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 => true,
102
- :color => true,
103
- :autosub => false,
104
- :fontsize => 18,
105
- :format => "png",
106
- :leafstyle => "auto",
107
- :filename => "syntree",
108
- :data => "",
109
- :margin => 0,
110
- :vheight => 1.0,
111
- :fontstyle => "sans",
112
- :font => "/NotoSansCJKjp-Regular.otf",
113
- :font_it => "/NotoSans-Italic.ttf",
114
- :font_bd => "/NotoSans-Bold.ttf",
115
- :font_bdit => "/NotoSans-BoldItalic.ttf",
116
- :font_math => "/NotoSansMath-Regular.ttf"
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 => 120,
121
+ :e_width => 0,
120
122
  :e_padd => 14,
121
123
  :v_space => 20,
122
- :h_space => 20,
123
- :b_side => 10,
124
- :b_topbot => 10
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.8.6
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-03 00:00:00.000000000 Z
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/NotoSansCJKjp-Regular.otf
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/NotoSerifCJKjp-Regular.otf
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