hokusai-zero 0.1.3 → 0.1.5

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +4 -0
  4. data/README.md +33 -83
  5. data/ast/src/core/hml.c +9 -9
  6. data/ast/src/core/text.c +21 -3
  7. data/ast/test/text.c +3 -3
  8. data/docs.sh +29 -0
  9. data/ext/extconf.rb +69 -14
  10. data/grammar/corpus/1_document.txt +24 -0
  11. data/grammar/corpus/6_styles.txt +23 -0
  12. data/grammar/grammar.js +4 -4
  13. data/grammar/src/grammar.json +19 -19
  14. data/grammar/src/parser.c +1904 -1956
  15. data/grammar/test.nml +10 -8
  16. data/hokusai.gemspec +3 -1
  17. data/ui/examples/assets/Delius-Regular.ttf +0 -0
  18. data/ui/examples/assets/DoHyeon.ttf +0 -0
  19. data/ui/examples/assets/Inter-Regular.ttf +0 -0
  20. data/ui/examples/assets/ernest.gif +0 -0
  21. data/ui/examples/assets/icons/audio-x-generic.png +0 -0
  22. data/ui/examples/assets/icons/image-x-generic.png +0 -0
  23. data/ui/examples/assets/icons/media-playback-pause.png +0 -0
  24. data/ui/examples/assets/icons/media-playback-start.png +0 -0
  25. data/ui/examples/assets/icons/media-playback-stop.png +0 -0
  26. data/ui/examples/assets/icons/package-x-generic.png +0 -0
  27. data/ui/examples/assets/icons/text-x-generic.png +0 -0
  28. data/ui/examples/assets/icons/video-x-generic.png +0 -0
  29. data/ui/examples/buddy.rb +16 -14
  30. data/ui/examples/clock.rb +38 -36
  31. data/ui/examples/counter.rb +100 -98
  32. data/ui/examples/dynamic.rb +115 -113
  33. data/ui/examples/foobar.rb +189 -187
  34. data/ui/examples/forum/file.rb +54 -0
  35. data/ui/examples/forum/music.rb +76 -0
  36. data/ui/examples/forum/post.rb +146 -0
  37. data/ui/examples/forum.rb +198 -0
  38. data/ui/examples/spreadsheet/csv.rb +261 -0
  39. data/ui/examples/spreadsheet.rb +138 -0
  40. data/ui/examples/stock.rb +86 -92
  41. data/ui/examples/stock_decider/option.rb +1 -1
  42. data/ui/examples/tic_tac_toe.rb +193 -191
  43. data/ui/lib/lib_hokusai.rb +2 -1
  44. data/ui/src/hokusai/assets/arrow-drop-down-line.png +0 -0
  45. data/ui/src/hokusai/assets/chevron-down.svg +1 -0
  46. data/ui/src/hokusai/assets/close-large-line.png +0 -0
  47. data/ui/src/hokusai/ast.rb +42 -43
  48. data/ui/src/hokusai/backends/raylib/font.rb +1 -2
  49. data/ui/src/hokusai/backends/raylib.rb +29 -17
  50. data/ui/src/hokusai/backends/sdl2/font.rb +13 -9
  51. data/ui/src/hokusai/backends/sdl2.rb +32 -5
  52. data/ui/src/hokusai/block.rb +14 -7
  53. data/ui/src/hokusai/blocks/dropdown.rb +205 -0
  54. data/ui/src/hokusai/blocks/hblock.rb +2 -2
  55. data/ui/src/hokusai/blocks/image.rb +6 -1
  56. data/ui/src/hokusai/blocks/input.rb +17 -0
  57. data/ui/src/hokusai/blocks/label.rb +5 -2
  58. data/ui/src/hokusai/blocks/modal.rb +62 -0
  59. data/ui/src/hokusai/blocks/panel.rb +2 -2
  60. data/ui/src/hokusai/blocks/scrollbar.rb +0 -2
  61. data/ui/src/hokusai/blocks/text.rb +12 -6
  62. data/ui/src/hokusai/blocks/titlebar/osx.rb +4 -4
  63. data/ui/src/hokusai/blocks/variable.rb +33 -0
  64. data/ui/src/hokusai/blocks/vblock.rb +1 -1
  65. data/ui/src/hokusai/commands/rect.rb +4 -4
  66. data/ui/src/hokusai/commands.rb +46 -29
  67. data/ui/src/hokusai/diff.rb +11 -0
  68. data/ui/src/hokusai/event.rb +19 -5
  69. data/ui/src/hokusai/events/mouse.rb +9 -1
  70. data/ui/src/hokusai/font.rb +60 -0
  71. data/ui/src/hokusai/meta.rb +11 -24
  72. data/ui/src/hokusai/node.rb +1 -1
  73. data/ui/src/hokusai/painter.rb +66 -8
  74. data/ui/src/hokusai/util/clamping_iterator.rb +5 -6
  75. data/ui/src/hokusai.rb +53 -4
  76. metadata +56 -3
@@ -1,4 +1,6 @@
1
1
  module Hokusai
2
+ # Represents a patch to move a loop item
3
+ # from one location to another
2
4
  class MovePatch
3
5
  attr_accessor :from, :to, :delete
4
6
 
@@ -9,6 +11,8 @@ module Hokusai
9
11
  end
10
12
  end
11
13
 
14
+ # Represents a patch to insert an item
15
+ # into the loop list
12
16
  class InsertPatch
13
17
  attr_accessor :target, :value, :delete
14
18
 
@@ -19,6 +23,8 @@ module Hokusai
19
23
  end
20
24
  end
21
25
 
26
+ # Represents a patch to update the value
27
+ # of a loop item at an index
22
28
  class UpdatePatch
23
29
  attr_accessor :target, :value
24
30
 
@@ -28,6 +34,7 @@ module Hokusai
28
34
  end
29
35
  end
30
36
 
37
+ # Patch to delete a loop list item
31
38
  class DeletePatch
32
39
  attr_accessor :target
33
40
 
@@ -36,6 +43,10 @@ module Hokusai
36
43
  end
37
44
  end
38
45
 
46
+ # A Differ for comparing one set of values to another
47
+ #
48
+ # When #patch is called, will yield various patches to
49
+ # true up the old values with the new values.
39
50
  class Diff
40
51
  attr_reader :before, :after, :insertions
41
52
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hokusai
4
+ # A Basic UI Event
4
5
  class Event
5
- attr_reader :captures, :bubbles
6
+ attr_reader :captures
6
7
  attr_accessor :stopped
7
8
 
9
+ # Sets the name of this event kind
8
10
  def self.name(name)
9
11
  @name = name
10
12
  end
@@ -13,33 +15,45 @@ module Hokusai
13
15
  self.class.instance_variable_get("@name")
14
16
  end
15
17
 
18
+ # Has the event stopped propagation?
19
+ # @return [Bool]
16
20
  def stopped
17
21
  @stopped ||= false
18
22
  end
19
23
 
24
+ # Stop propagation on this event
25
+ # @return [Void]
20
26
  def stop
21
27
  self.stopped = true
22
28
  end
23
29
 
30
+ # @return [Array<Block>] the captured blocks for this event
24
31
  def captures
25
32
  @captures ||= []
26
33
  end
27
34
 
28
- def bubbles
29
- @bubbles ||= []
30
- end
31
-
35
+ # A JSON string representing this event
36
+ #
37
+ # Used in automation
38
+ # @return [String]
32
39
  def to_json
33
40
  raise Hokusai::Error.new("#{self.class} must implement to_json")
34
41
  end
35
42
 
43
+ # Does the event match the provided Hokusai::Block?
44
+ #
45
+ # @param [Hokusai::Block]
46
+ # @return [Bool]
36
47
  def matches(block)
37
48
  return false if block.node.portal.nil?
38
49
 
39
50
  val = block.node.portal.ast.event(name)
51
+
40
52
  !!val
41
53
  end
42
54
 
55
+ # Emit the event to all captured blocks,
56
+ # stopping if any of the blocks stop propagation
43
57
  def bubble
44
58
  while block = captures.pop
45
59
  block.emit(name, self)
@@ -165,8 +165,16 @@ module Hokusai
165
165
  class MouseOutEvent < MouseEvent
166
166
  name "mouseout"
167
167
 
168
- def capture(block, _)
168
+ def capture(block, canvas)
169
169
  captures << block if matches(block)
170
+
171
+ if left[:clicked] && !clicked(canvas)
172
+ block.node.meta.blur
173
+ end
174
+ end
175
+
176
+ def clicked(canvas)
177
+ LibHokusai.hoku_input_is_clicked(input.raw, canvas.to_hoku_rect)
170
178
  end
171
179
  end
172
180
  end
@@ -1,29 +1,54 @@
1
1
  module Hokusai
2
+ # A Backend agnostic font interface
3
+ #
4
+ # Backends are expected to implement the following methods
2
5
  class Font
6
+ # Creates a wrapping of text based on container width and font size
7
+ #
8
+ # @param [String] the text to wrap
9
+ # @param [Integer] the font size
10
+ # @param [Float] the width of the container
11
+ # @param [Float] an initital offset
12
+ # @return [Hokusai::Clamping]
3
13
  def clamp(text, size, width, initial_offset = 0.0)
4
14
  raise Hokusai::Error.new("Font #clamp not implemented")
5
15
  end
6
16
 
17
+ # Creates a wrapping of text based on the container width and font size
18
+ # and parses markdown
19
+ # @param [String] the text to wrap
20
+ # @param [Integer] the font size
21
+ # @param [Float] the width of the container
22
+ # @param [Float] an initital offset
23
+ # @return [Hokusai::Clamping]
7
24
  def clamp_markdown(text, size, width, initial_offset = 0.0)
8
25
  raise Hokusai::Error.new("Font #clamp not implemented")
9
26
  end
10
27
 
28
+ # @return [Integer] the font height
11
29
  def height
12
30
  raise Hokusai::Error.new("Font #height not implemented")
13
31
  end
14
32
  end
15
33
 
34
+ # A class representing wrapped text
35
+ #
36
+ # A clamping has many segments, delimited by a newline
37
+ # A segment has many possible groups, and a group has many possible charss
16
38
  class Clamping
17
39
  class Char
18
40
  attr_reader :raw
41
+
19
42
  def initialize(raw)
20
43
  @raw = raw
21
44
  end
22
45
 
46
+ # @return [Float] the width of the char
23
47
  def width
24
48
  raw[:width]
25
49
  end
26
50
 
51
+ # @return [Integer] the offset of the char relative to the clamping
27
52
  def offset
28
53
  raw[:offset]
29
54
  end
@@ -36,46 +61,57 @@ module Hokusai
36
61
  @raw = raw
37
62
  end
38
63
 
64
+ # @return [Integer] the offset of the group relative to the clamping
39
65
  def offset
40
66
  @offset ||= raw[:offset]
41
67
  end
42
68
 
69
+ # @return [Integer] number of chars in this group
43
70
  def size
44
71
  @size ||= raw[:size]
45
72
  end
46
73
 
74
+ # @return [Float] the total width of chars in this group
47
75
  def width
48
76
  chars.sum(&:width)
49
77
  end
50
78
 
79
+ # @return [UInt] a flag for this group type
51
80
  def type
52
81
  @type ||= raw[:type]
53
82
  end
54
83
 
84
+ # @return [Bool] is this group normal?
55
85
  def normal?
56
86
  @normal ||= type == LibHokusai::GROUP_NORMAL
57
87
  end
58
88
 
89
+ # @return [Bool] is this group bold?
59
90
  def bold?
60
91
  @bold ||= ((type & LibHokusai::GROUP_BOLD) != 0)
61
92
  end
62
93
 
94
+ # @return [Bool] is this group italics?
63
95
  def italics?
64
96
  @italics ||= ((type & LibHokusai::GROUP_ITALICS) != 0)
65
97
  end
66
98
 
99
+ # @return [Bool] does this group represent a hyperlink?
67
100
  def link?
68
101
  @link ||= ((type & LibHokusai::GROUP_LINK) != 0)
69
102
  end
70
103
 
104
+ # @return [Bool] does this group represent a code block?
71
105
  def code?
72
106
  @code ||= type & LibHokusai::GROUP_CODE
73
107
  end
74
108
 
109
+ # @return [String] the hyperlink for this group if there is one
75
110
  def link
76
111
  @href ||= raw[:payload].read_string
77
112
  end
78
113
 
114
+ # @return [Array<Hokusai::Char>] an array of chars
79
115
  def chars
80
116
  return @chars unless @chars.nil?
81
117
 
@@ -106,18 +142,23 @@ module Hokusai
106
142
  @raw = raw
107
143
  end
108
144
 
145
+ # A segment width given a range of offsets
146
+ # NOTE: Defaults to the full segment
109
147
  def width(range = (offset...offset + size))
110
148
  chars[range]&.sum(&:width) || 0.0
111
149
  end
112
150
 
151
+ # @return [Integer] the offset of this segment relative to the clamping
113
152
  def offset
114
153
  raw[:offset]
115
154
  end
116
155
 
156
+ # @return [Integer] the number of chars in this segment
117
157
  def size
118
158
  raw[:size]
119
159
  end
120
160
 
161
+ # @return [Array<Hokusai::Char>] an array of chars
121
162
  def chars
122
163
  return @chars unless @chars.nil?
123
164
 
@@ -140,6 +181,7 @@ module Hokusai
140
181
  end
141
182
  end
142
183
 
184
+ # @return [Array<Hokusai::Group>] an array of clamping groups
143
185
  def groups
144
186
  return @groups unless @groups.nil?
145
187
 
@@ -243,6 +285,7 @@ module Hokusai
243
285
  end
244
286
  end
245
287
 
288
+ # Keeps track of any loaded fonts
246
289
  class FontRegistry
247
290
  attr_reader :fonts, :active_font
248
291
 
@@ -251,28 +294,45 @@ module Hokusai
251
294
  @active_font = nil
252
295
  end
253
296
 
297
+ # Registers a font
298
+ #
299
+ # @param [String] the name of the font
300
+ # @param [Hokusai::Font] a font
254
301
  def register(name, font)
255
302
  raise Hokusai::Error.new("Font #{name} already registered") if fonts[name]
256
303
 
257
304
  fonts[name] = font
258
305
  end
259
306
 
307
+ # Returns the active font's name
308
+ #
309
+ # @return [String]
260
310
  def active_font_name
261
311
  raise Hokusai::Error.new("No active font") if active_font.nil?
262
312
 
263
313
  active_font
264
314
  end
265
315
 
316
+ # Activates a font by name
317
+ #
318
+ # @param [String] the name of the registered font
266
319
  def activate(name)
267
320
  raise Hokusai::Error.new("Font #{name} is not registered") unless fonts[name]
268
321
 
269
322
  @active_font = name
270
323
  end
271
324
 
325
+ # Fetches a font
326
+ #
327
+ # @param [String] the name of the registered font
328
+ # @return [Hokusai::Font]
272
329
  def get(name)
273
330
  fonts[name]
274
331
  end
275
332
 
333
+ # Fetches the active font
334
+ #
335
+ # @return [Hokusai::Font]
276
336
  def active
277
337
  fonts[active_font]
278
338
  end
@@ -5,7 +5,7 @@ module Hokusai
5
5
  attr_reader :focused, :parent, :target, :updater,
6
6
  :props, :publisher
7
7
 
8
- def self.commands
8
+ def commands
9
9
  @commands ||= Commands.new
10
10
  end
11
11
 
@@ -105,24 +105,18 @@ module Hokusai
105
105
  end
106
106
 
107
107
  def update(block)
108
- # pp props
109
- # if parent_block = parent
110
- if target_block = target
111
- if updater_block = updater
112
- # Hokusai::Pool.post do
113
- block.public_send(:before_updated) if block.respond_to?(:before_updated)
114
-
115
- updater_block.call(block, target_block, target_block)
116
- block.public_send(:after_updated) if block.respond_to?(:after_updated)
117
-
118
- # end
119
- end
120
- end
121
- # end
108
+ if target_block = target
109
+ if updater_block = updater
110
+ block.public_send(:before_updated) if block.respond_to?(:before_updated)
122
111
 
123
- children?&.each do |child|
124
- child.update
112
+ updater_block.call(block, target_block, target_block)
113
+ block.public_send(:after_updated) if block.respond_to?(:after_updated)
125
114
  end
115
+ end
116
+
117
+ children?&.each do |child|
118
+ child.update
119
+ end
126
120
  end
127
121
 
128
122
  def has_ast?(ast, index)
@@ -132,13 +126,6 @@ module Hokusai
132
126
 
133
127
  false
134
128
  end
135
- #
136
- # def destroy
137
- # children.each do |child|
138
- # child.before_destroy if child.respond_to?(:before_destroy)
139
- # child.node.destroy
140
- # end
141
- # end
142
129
 
143
130
  def child_delete(index)
144
131
  if child = children![index]
@@ -83,7 +83,7 @@ module Hokusai
83
83
  elsif context&.table&.[](method)
84
84
  value = context.table[method]
85
85
  else
86
- value = block.public_send(method)
86
+ value = block.instance_eval(method)
87
87
  end
88
88
  else
89
89
  value = method
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "./event"
4
+ require "colorize"
4
5
 
5
6
  module Hokusai
6
7
  class PainterEntry
@@ -22,6 +23,9 @@ module Hokusai
22
23
  end
23
24
  end
24
25
 
26
+ ZTARGET_ROOT = "root"
27
+ ZTARGET_PARENT = "parent"
28
+
25
29
  class Painter
26
30
  attr_reader :root, :input, :before_render, :after_render,
27
31
  :events
@@ -52,17 +56,36 @@ module Hokusai
52
56
  @after_render = block
53
57
  end
54
58
 
59
+ # def debug(parent, children)
60
+ # @i ||= 0
61
+
62
+ # pp [
63
+ # "#{@i}",
64
+ # "parent: #{parent.block.class}##{parent.block.node.portal&.ast&.id} (z: #{parent.block.node.meta.get_prop(:z)})",
65
+ # "children: #{children.map {|c| "#{c.block.class}##{c.block.node.portal&.ast&.id} (z: #{c.block.node.meta.get_prop(:z)})"} }"
66
+ # ]
67
+ # @i += 1
68
+ # end
69
+
55
70
  # @return [Array(Commands::Base)] the command list
56
71
  def render(canvas, resize = false, capture: true)
57
72
  return if root.children.empty?
58
73
 
74
+ zindexed = {}
75
+ zindex_counter = 0
76
+ zroot_x = canvas.x
77
+ zroot_y = canvas.y
78
+ zroot_w = canvas.width
79
+ zroot_h = canvas.height
80
+
59
81
  @root.on_resize(canvas) if resize
60
82
 
61
83
  before_render&.call([root, nil], canvas, input)
62
84
 
63
85
  root_children = (canvas.reverse? ? root.children?&.reverse.dup : root.children?&.dup) || []
64
86
  groups = []
65
- groups << [root, measure(root_children, canvas)]
87
+ root_entry = PainterEntry.new(root, canvas.x, canvas.y, canvas.width, canvas.height)
88
+ groups << [root_entry, measure(root_children, canvas)]
66
89
 
67
90
  mouse_y = input.mouse.pos[:y]
68
91
  can_capture = mouse_y >= (canvas.y || 0.0) && mouse_y <= (canvas.y || 0.0) + canvas.height
@@ -71,13 +94,29 @@ module Hokusai
71
94
 
72
95
  while payload = groups.pop
73
96
  group_parent, group_children = payload
97
+
98
+ parent_z = group_parent.block.node.meta.get_prop(:z)&.to_i
99
+ zindex_counter -= 1 if (parent_z || 0) > 0 && group_children.empty?
74
100
 
75
101
  while group = group_children.shift
76
- canvas.reset(group.x, group.y, group.w, group.h)
102
+ z = group.block.node.meta.get_prop(:z)&.to_i || 0
103
+ ztarget = group.block.node.meta.get_prop(:ztarget)
104
+ entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h)
105
+
106
+ if (zindex_counter > 0 || z > 0)
107
+ case ztarget
108
+ when ZTARGET_ROOT
109
+ entry = PainterEntry.new(group.block, zroot_x || 0.0, zroot_y || 0.0, zroot_w, zroot_h).freeze
110
+ when ZTARGET_PARENT
111
+ entry = PainterEntry.new(group.block, group_parent.x || 0.0, group_parent.y || 0.0, group_parent.w, group_parent.h).freeze
112
+ end
113
+ end
114
+
115
+ canvas.reset(entry.x, entry.y, entry.w, entry.h)
77
116
 
78
117
  before_render&.call([group.block, group.parent], canvas, input.raw)
79
118
 
80
- if capture && can_capture
119
+ if capture
81
120
  capture_events(group.block, canvas, hovered: hovered)
82
121
  end
83
122
 
@@ -92,17 +131,36 @@ module Hokusai
92
131
 
93
132
  unless local_children.nil?
94
133
  groups << [group_parent, group_children]
95
- groups << [group.block, measure(local_children, local_canvas)]
134
+ parent = PainterEntry.new(group.block, canvas.x, canvas.y, canvas.width, canvas.height)
135
+ groups << [parent, measure(local_children, local_canvas)]
136
+
96
137
  breaked = true
97
138
  else
98
139
  breaked = false
99
140
  end
100
141
  end
142
+
143
+ if z > 0
144
+ zindex_counter += 1
145
+ # puts ["start (#{z}) <#{parent_z}> {#{zindex_counter}} #{group.block.class}".colorize(:blue), z, group.block.node.portal&.ast&.id]
146
+ zindexed[zindex_counter] ||= []
147
+ zindexed[zindex_counter] << group.block
148
+ elsif zindex_counter > 0
149
+ # puts ["push (#{z}) <#{parent_z}> {#{zindex_counter}} initial #{group.block.class}".colorize(:red), z, group.block.node.portal&.ast&.id]
150
+ zindexed[zindex_counter] << group.block
151
+ else
152
+ # puts ["draw (#{z}) <#{parent_z}> {#{zindex_counter}} #{group.block.class}".colorize(:yellow), z, group.block.node.portal&.ast&.id]
153
+ group.block.execute_draw
154
+ end
101
155
 
102
156
  break if breaked
103
157
  end
104
158
  end
105
159
 
160
+ zindexed.sort.each do |z, blocks|
161
+ blocks.each(&:execute_draw)
162
+ end
163
+
106
164
  if capture
107
165
  events[:hover].bubble
108
166
  events[:wheel].bubble
@@ -132,10 +190,12 @@ module Hokusai
132
190
  hsum = 0.0
133
191
 
134
192
  children.each do |block|
135
- # children.each do |block|
193
+ z = block.node.meta.get_prop?(:z)&.to_i || 0
136
194
  h = block.node.meta.get_prop?(:height)&.to_f
137
195
  w = block.node.meta.get_prop?(:width)&.to_f
138
196
 
197
+ next if z > 0
198
+
139
199
  if w
140
200
  wsum += w
141
201
  wcount = wcount.succ
@@ -188,7 +248,6 @@ module Hokusai
188
248
  return
189
249
  end
190
250
 
191
-
192
251
  rect = canvas.to_hoku_rect
193
252
  block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)
194
253
 
@@ -196,12 +255,11 @@ module Hokusai
196
255
  events[:hover].capture(block, canvas)
197
256
  events[:click].capture(block, canvas)
198
257
  events[:wheel].capture(block, canvas)
199
- events[:mousedown].capture(block, canvas)
200
258
  events[:mouseup].capture(block, canvas)
259
+ events[:mousedown].capture(block, canvas)
201
260
  else
202
261
  events[:mouseout].capture(block, canvas)
203
262
  end
204
-
205
263
  events[:mousemove].capture(block, canvas)
206
264
 
207
265
  if block_is_hovered || block.node.meta.focused
@@ -15,9 +15,9 @@ module Hokusai::Util
15
15
  end
16
16
 
17
17
  def draw(font_size, boundary, selection: nil)
18
- selection_extract(font_size, boundary, selection: selection)
18
+ # selection_extract(font_size, boundary, selection: selection)
19
19
  draw_text(font_size, boundary)
20
- selection_update(selection)
20
+ # selection_update(selection)
21
21
  # self.start_select = 0.0
22
22
  # self.stop_select = nil
23
23
  end
@@ -85,17 +85,16 @@ module Hokusai::Util
85
85
  x = @iterator.x
86
86
 
87
87
  if @iterator.clamping.markdown
88
-
89
88
  segment.groups.each do |group|
90
89
  text = iterator.clamping[group.offset, group.size]
91
90
 
92
- if text == " "
93
- x += group.width * 2
94
-
91
+ if text == "\n"
95
92
  next
93
+ # x += group.width
96
94
  end
97
95
 
98
96
  @iterator.on_draw_cb&.call(text, x, y, group)
97
+
99
98
  x += group.width
100
99
  end
101
100
  else