rsyntaxtree 0.8.8 → 1.0.1

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,309 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
-
4
- #==========================
5
- # tree_graph.rb
6
- #==========================
7
- #
8
- # Parses an element list into a (non-SVG) graphical tree.
9
- #
10
- # This file is part of RSyntaxTree, which is a ruby port of Andre Eisenbach's
11
- # excellent program phpSyntaxTree.
12
- #
13
- # Copyright (c) 2007-2021 Yoichiro Hasebe <yohasebe@gmail.com>
14
- # Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
15
-
16
- require 'graph'
17
- require 'rmagick'
18
- include Magick
19
-
20
- class TreeGraph < Graph
21
-
22
- def initialize(e_list, metrics, symmetrize, color, leafstyle, multibyte,
23
- fontstyle, font, font_it, font_bd, font_itbd, font_math, font_cjk, font_size,
24
- margin, transparent)
25
-
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
36
- @transparent = transparent
37
-
38
- super(e_list, metrics, symmetrize, color, leafstyle, multibyte, @font, @font_size)
39
-
40
- # Initialize the image and colors
41
- @gc = Draw.new
42
- @gc.font = @font
43
- @gc.pointsize(@font_size)
44
- end
45
-
46
- def destroy
47
- @im.destroy!
48
- end
49
-
50
- def draw
51
- parse_list
52
- @im = Image.new(@width, @height)
53
- if @transparent
54
- @im.matte_reset!
55
- end
56
- @im.interlace = PlaneInterlace
57
- @gc.draw(@im)
58
- end
59
-
60
- def save(filename)
61
- draw
62
- @im.write(filename)
63
- end
64
-
65
- # inspired by the implementation of Gruff
66
- # by Geoffrey Grosenbach
67
- def to_blob(fileformat='PNG')
68
- draw
69
- @im.trim!
70
- if @transparent
71
- @im.border!(@margin, @margin, "transparent")
72
- else
73
- @im.border!(@margin, @margin, "white")
74
- end
75
- @im.format = fileformat
76
- @im.interlace = PlaneInterlace
77
- return @im.to_blob
78
- end
79
-
80
- :private
81
-
82
- # Add the element into the tree (draw it)
83
- def draw_element(x, y, w, string, type)
84
- numlines = string.count("\n")
85
- string = string.sub(/\^\z/){""}
86
- # Calculate element dimensions and position
87
- if (type == ETYPE_LEAF) and @leafstyle == "nothing"
88
- top = row2px(y - 1) + (@font_size * 1.5)
89
- else
90
- top = row2px(y)
91
- end
92
- left = x + @m[:b_side]
93
- bottom = top + @e_height * numlines
94
- right = left + w
95
-
96
- # Split the string into the main part and the
97
- # subscript part of the element (if any)
98
- parts = string.split("_", 2)
99
- if(parts.length > 1 )
100
- main = parts[0].strip
101
- sub = parts[1].gsub(/_/, " ").strip
102
- else
103
- main = parts[0].strip
104
- sub = ""
105
- end
106
-
107
- if /\A\=(.+)\=\z/ =~ main
108
- main = $1
109
- main_decoration = OverlineDecoration
110
- elsif /\A\-(.+)\-\z/ =~ main
111
- main = $1
112
- main_decoration = UnderlineDecoration
113
- elsif /\A\~(.+)\~\z/ =~ main
114
- main = $1
115
- main_decoration = LineThroughDecoration
116
- else
117
- main_decoration = NoDecoration
118
- end
119
-
120
- main_font = @font
121
-
122
- if /\A\*\*\*(.+)\*\*\*\z/ =~ main
123
- main = $1
124
- if !@multibyte
125
- main_font = @font_itbd
126
- end
127
- elsif /\A\*\*(.+)\*\*\z/ =~ main
128
- main = $1
129
- if !@multibyte
130
- main_font = @font_bd
131
- end
132
- elsif /\A\*(.+)\*\z/ =~ main
133
- main = $1
134
- if !@multibyte
135
- main_font = @font_it
136
- end
137
- end
138
-
139
- if /\A#(.+)#\z/ =~ main
140
- main = $1
141
- main_font = @font_math
142
- end
143
-
144
- # Calculate text size for the main and the
145
- # subscript part of the element
146
-
147
- main_width = img_get_txt_width(main, main_font, @font_size)
148
-
149
- if /\A\=(.+)\=\z/ =~ sub
150
- sub = $1
151
- sub_decoration = OverlineDecoration
152
- elsif /\A\-(.+)\-\z/ =~ sub
153
- sub = $1
154
- sub_decoration = UnderlineDecoration
155
- elsif /\A\~(.+)\~z/ =~ sub
156
- sub = $1
157
- sub_decoration = LineThroughDecoration
158
- else
159
- sub_decoration = NoDecoration
160
- end
161
-
162
- sub_font = @font
163
- if /\A\*\*\*(.+)\*\*\*\z/ =~ sub
164
- sub = $1
165
- if !@multibyte
166
- sub_font = @font_itbd
167
- end
168
- elsif /\A\*\*(.+)\*\*\z/ =~ sub
169
- sub = $1
170
- if !@multibyte
171
- sub_font = @font_bd
172
- end
173
- elsif /\A\*(.+)\*\z/ =~ sub
174
- sub = $1
175
- if !@multibyte
176
- sub_font = @font_it
177
- end
178
- end
179
-
180
- if /\A#(.+)#\z/ =~ sub
181
- sub = $1
182
- sub_font = @font_math
183
- end
184
-
185
- if sub != ""
186
- sub_width = img_get_txt_width(sub.to_s, sub_font, @sub_size)
187
- else
188
- sub_width = 0
189
- end
190
-
191
- # Center text in the element
192
- txt_width = main_width + sub_width
193
-
194
- txt_pos = left + (right - left) / 2 - txt_width / 2
195
-
196
- # Select apropriate color
197
- if(type == ETYPE_LEAF)
198
- col = @col_leaf
199
- else
200
- col = @col_node
201
- end
202
-
203
- if(main[0].chr == "<" && main[-1].chr == ">")
204
- col = @col_trace
205
- end
206
-
207
- @gc.stroke("none")
208
- @gc.fill(col)
209
-
210
- # Draw main text
211
- @gc.pointsize(@font_size)
212
- main_x = txt_pos
213
- main_y = top + @e_height - @m[:e_padd]
214
-
215
- @gc.interline_spacing = -(@main_height / 3)
216
- @gc.font(main_font)
217
- @gc.decorate(main_decoration)
218
- @gc.text(main_x.ceil, main_y.ceil, main)
219
-
220
- # Draw subscript text
221
- if (sub.length > 0 )
222
- @gc.pointsize(@sub_size)
223
- sub_x = txt_pos + main_width + @sub_space_width
224
- sub_y = top + (@e_height - @m[:e_padd] + @sub_size / 2)
225
- @gc.font(sub_font)
226
- @gc.decorate(sub_decoration)
227
- @gc.text(sub_x.ceil, sub_y.ceil, sub)
228
- end
229
- end
230
-
231
- # Draw a line between child/parent elements
232
- def line_to_parent(fromX, fromY, fromW, toX, toW)
233
-
234
- if (fromY == 0 )
235
- return
236
- end
237
-
238
- fromTop = row2px(fromY)
239
- fromLeft = (fromX + fromW / 2 + @m[:b_side])
240
- toBot = (row2px(fromY - 1 ) + @e_height)
241
- toLeft = (toX + toW / 2 + @m[:b_side])
242
-
243
- @gc.fill("none")
244
- @gc.stroke @col_line
245
- @gc.stroke_width 1 * FONT_SCALING
246
- @gc.line(fromLeft.ceil, fromTop.ceil, toLeft.ceil, toBot.ceil)
247
- end
248
-
249
- # Draw a triangle between child/parent elements
250
- def triangle_to_parent(fromX, fromY, fromW, textW, symmetrize = true)
251
- if (fromY == 0)
252
- return
253
- end
254
-
255
- toX = fromX
256
- fromCenter = (fromX + fromW / 2 + @m[:b_side])
257
-
258
- fromTop = row2px(fromY).ceil
259
- fromLeft1 = (fromCenter + textW / 2).ceil
260
- fromLeft2 = (fromCenter - textW / 2).ceil
261
- toBot = (row2px(fromY - 1) + @e_height)
262
- if symmetrize
263
- toLeft = (toX + textW / 2 + @m[:b_side])
264
- else
265
- toLeft = (toX + textW / 2 + @m[:b_side] * 3)
266
- end
267
-
268
- @gc.fill("none")
269
- @gc.stroke @col_line
270
- @gc.stroke_width 1 * 2
271
- @gc.line(fromLeft1, fromTop, toLeft, toBot)
272
- @gc.line(fromLeft2, fromTop, toLeft, toBot)
273
- @gc.line(fromLeft1, fromTop, fromLeft2, fromTop)
274
- end
275
-
276
- # If a node element text is wider than the sum of it's
277
- # child elements, then the child elements need to
278
- # be resized to even out the space. This function
279
- # recurses down the a child tree and sizes the
280
- # children appropriately.
281
- def fix_child_size(id, current, target)
282
- children = @e_list.get_children(id)
283
- @e_list.set_element_width(id, target)
284
-
285
- if(children.length > 0 )
286
- delta = target - current
287
- target_delta = delta / children.length
288
-
289
- children.each do |child|
290
- child_width = @e_list.get_element_width(child)
291
- fix_child_size(child, child_width, child_width + target_delta)
292
- end
293
- end
294
- end
295
-
296
- def img_get_txt_width(text, font, font_size, multiline = true)
297
- parts = text.split("_", 2)
298
- main_before = parts[0].strip
299
- sub = parts[1]
300
- main = get_txt_only(main_before)
301
- main_metrics = img_get_txt_metrics(main, font, font_size, multiline)
302
- width = main_metrics.width
303
- if sub
304
- sub_metrics = img_get_txt_metrics(sub.strip, font, font_size * SUBSCRIPT_CONST, multiline)
305
- width += sub_metrics.width
306
- end
307
- return width
308
- end
309
- end