konpeito 0.1.0

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 (180) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +75 -0
  4. data/CONTRIBUTING.md +123 -0
  5. data/LICENSE +21 -0
  6. data/README.md +257 -0
  7. data/Rakefile +11 -0
  8. data/bin/konpeito +6 -0
  9. data/konpeito.gemspec +43 -0
  10. data/lib/konpeito/ast/typed_ast.rb +620 -0
  11. data/lib/konpeito/ast/visitor.rb +78 -0
  12. data/lib/konpeito/cache/cache_manager.rb +230 -0
  13. data/lib/konpeito/cache/dependency_graph.rb +192 -0
  14. data/lib/konpeito/cache.rb +8 -0
  15. data/lib/konpeito/cli/base_command.rb +187 -0
  16. data/lib/konpeito/cli/build_command.rb +220 -0
  17. data/lib/konpeito/cli/check_command.rb +104 -0
  18. data/lib/konpeito/cli/config.rb +231 -0
  19. data/lib/konpeito/cli/deps_command.rb +128 -0
  20. data/lib/konpeito/cli/doctor_command.rb +340 -0
  21. data/lib/konpeito/cli/fmt_command.rb +199 -0
  22. data/lib/konpeito/cli/init_command.rb +312 -0
  23. data/lib/konpeito/cli/lsp_command.rb +40 -0
  24. data/lib/konpeito/cli/run_command.rb +150 -0
  25. data/lib/konpeito/cli/test_command.rb +248 -0
  26. data/lib/konpeito/cli/watch_command.rb +212 -0
  27. data/lib/konpeito/cli.rb +301 -0
  28. data/lib/konpeito/codegen/builtin_methods.rb +229 -0
  29. data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
  30. data/lib/konpeito/codegen/debug_info.rb +352 -0
  31. data/lib/konpeito/codegen/inliner.rb +486 -0
  32. data/lib/konpeito/codegen/jvm_backend.rb +197 -0
  33. data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
  34. data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
  35. data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
  36. data/lib/konpeito/codegen/monomorphizer.rb +359 -0
  37. data/lib/konpeito/codegen/profile_runtime.c +341 -0
  38. data/lib/konpeito/codegen/profiler.rb +99 -0
  39. data/lib/konpeito/compiler.rb +592 -0
  40. data/lib/konpeito/dependency_resolver.rb +296 -0
  41. data/lib/konpeito/diagnostics/collector.rb +127 -0
  42. data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
  43. data/lib/konpeito/diagnostics/renderer.rb +144 -0
  44. data/lib/konpeito/formatter/formatter.rb +1214 -0
  45. data/lib/konpeito/hir/builder.rb +7167 -0
  46. data/lib/konpeito/hir/nodes.rb +2465 -0
  47. data/lib/konpeito/lsp/document_manager.rb +820 -0
  48. data/lib/konpeito/lsp/server.rb +183 -0
  49. data/lib/konpeito/lsp/transport.rb +38 -0
  50. data/lib/konpeito/parser/prism_adapter.rb +65 -0
  51. data/lib/konpeito/platform.rb +103 -0
  52. data/lib/konpeito/profile/report.rb +136 -0
  53. data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
  54. data/lib/konpeito/stdlib/compression/compression.rb +72 -0
  55. data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
  56. data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
  57. data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
  58. data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
  59. data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
  60. data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
  61. data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
  62. data/lib/konpeito/stdlib/http/extconf.rb +19 -0
  63. data/lib/konpeito/stdlib/http/http.rb +125 -0
  64. data/lib/konpeito/stdlib/http/http.rbs +57 -0
  65. data/lib/konpeito/stdlib/http/http_native.c +440 -0
  66. data/lib/konpeito/stdlib/json/extconf.rb +17 -0
  67. data/lib/konpeito/stdlib/json/json.rb +44 -0
  68. data/lib/konpeito/stdlib/json/json.rbs +33 -0
  69. data/lib/konpeito/stdlib/json/json_native.c +286 -0
  70. data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
  71. data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
  72. data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
  73. data/lib/konpeito/stdlib/ui/ui.rb +318 -0
  74. data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
  75. data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
  76. data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
  77. data/lib/konpeito/type_checker/inferrer.rb +565 -0
  78. data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
  79. data/lib/konpeito/type_checker/type_resolver.rb +276 -0
  80. data/lib/konpeito/type_checker/types.rb +1434 -0
  81. data/lib/konpeito/type_checker/unification.rb +323 -0
  82. data/lib/konpeito/ui/animation/animated_state.rb +80 -0
  83. data/lib/konpeito/ui/animation/easing.rb +59 -0
  84. data/lib/konpeito/ui/animation/value_tween.rb +66 -0
  85. data/lib/konpeito/ui/app.rb +379 -0
  86. data/lib/konpeito/ui/box.rb +38 -0
  87. data/lib/konpeito/ui/castella.rb +70 -0
  88. data/lib/konpeito/ui/castella_native.rb +76 -0
  89. data/lib/konpeito/ui/chart/area_chart.rb +305 -0
  90. data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
  91. data/lib/konpeito/ui/chart/base_chart.rb +210 -0
  92. data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
  93. data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
  94. data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
  95. data/lib/konpeito/ui/chart/line_chart.rb +289 -0
  96. data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
  97. data/lib/konpeito/ui/chart/scales.rb +77 -0
  98. data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
  99. data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
  100. data/lib/konpeito/ui/column.rb +271 -0
  101. data/lib/konpeito/ui/core.rb +2199 -0
  102. data/lib/konpeito/ui/dsl.rb +443 -0
  103. data/lib/konpeito/ui/frame.rb +171 -0
  104. data/lib/konpeito/ui/frame_native.rb +494 -0
  105. data/lib/konpeito/ui/markdown/ast.rb +124 -0
  106. data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
  107. data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
  108. data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
  109. data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
  110. data/lib/konpeito/ui/markdown/parser.rb +805 -0
  111. data/lib/konpeito/ui/markdown/renderer.rb +639 -0
  112. data/lib/konpeito/ui/markdown/theme.rb +165 -0
  113. data/lib/konpeito/ui/render_node.rb +260 -0
  114. data/lib/konpeito/ui/row.rb +207 -0
  115. data/lib/konpeito/ui/spacer.rb +18 -0
  116. data/lib/konpeito/ui/style.rb +799 -0
  117. data/lib/konpeito/ui/theme.rb +563 -0
  118. data/lib/konpeito/ui/themes/material.rb +35 -0
  119. data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
  120. data/lib/konpeito/ui/widgets/button.rb +103 -0
  121. data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
  122. data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
  123. data/lib/konpeito/ui/widgets/container.rb +91 -0
  124. data/lib/konpeito/ui/widgets/data_table.rb +667 -0
  125. data/lib/konpeito/ui/widgets/divider.rb +29 -0
  126. data/lib/konpeito/ui/widgets/image.rb +105 -0
  127. data/lib/konpeito/ui/widgets/input.rb +485 -0
  128. data/lib/konpeito/ui/widgets/markdown.rb +57 -0
  129. data/lib/konpeito/ui/widgets/modal.rb +163 -0
  130. data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
  131. data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
  132. data/lib/konpeito/ui/widgets/net_image.rb +100 -0
  133. data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
  134. data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
  135. data/lib/konpeito/ui/widgets/slider.rb +133 -0
  136. data/lib/konpeito/ui/widgets/switch.rb +84 -0
  137. data/lib/konpeito/ui/widgets/tabs.rb +157 -0
  138. data/lib/konpeito/ui/widgets/text.rb +110 -0
  139. data/lib/konpeito/ui/widgets/tree.rb +426 -0
  140. data/lib/konpeito/version.rb +5 -0
  141. data/lib/konpeito.rb +109 -0
  142. data/test_native_array.rb +172 -0
  143. data/test_native_array_class.rb +197 -0
  144. data/test_native_class.rb +151 -0
  145. data/tools/konpeito-asm/build.sh +65 -0
  146. data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
  147. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
  148. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
  149. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
  150. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
  151. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
  152. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
  153. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
  154. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
  155. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
  156. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
  157. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
  158. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
  159. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
  160. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
  161. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
  162. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
  163. data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
  164. data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
  165. data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
  166. data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
  167. data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
  168. data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
  169. data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
  170. data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
  171. data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
  172. data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
  173. data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
  174. data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
  175. data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
  176. data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
  177. data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
  178. data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
  179. data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
  180. metadata +267 -0
@@ -0,0 +1,494 @@
1
+ # rbs_inline: enabled
2
+
3
+ # NativeFrame - bridges KonpeitoUI (SDL3 + Skia) to the Castella App
4
+ # LLVM backend equivalent of JWMFrame (JVM backend)
5
+ #
6
+ # Key difference from JWMFrame: polling model instead of callbacks.
7
+ # SDL3 events are polled each frame instead of pushed via SAM callbacks.
8
+ #
9
+ # Painter methods use snake_case (matching Ruby conventions).
10
+ # JVM widgets call painter.draw_text(...) which RubyDispatch auto-converts
11
+ # to drawText; NativeFrame exposes snake_case directly.
12
+
13
+ # Try to load native extension, fall back to Ruby stub
14
+ begin
15
+ require_relative "../stdlib/ui/konpeito_ui"
16
+ rescue LoadError
17
+ require_relative "../stdlib/ui/ui"
18
+ end
19
+
20
+ class NativeFrame
21
+ # Event type constants (from KonpeitoUI)
22
+ EVENT_NONE = 0
23
+ EVENT_MOUSE_DOWN = 1
24
+ EVENT_MOUSE_UP = 2
25
+ EVENT_MOUSE_MOVE = 3
26
+ EVENT_MOUSE_WHEEL = 4
27
+ EVENT_KEY_DOWN = 5
28
+ EVENT_KEY_UP = 6
29
+ EVENT_TEXT_INPUT = 7
30
+ EVENT_RESIZE = 8
31
+ EVENT_IME_PREEDIT = 9
32
+ EVENT_QUIT = 10
33
+
34
+ #: (String title, Integer width, Integer height) -> void
35
+ def initialize(title, width, height)
36
+ @handle = KonpeitoUI.create_window(title, width, height)
37
+ @running = false
38
+ @on_redraw = nil
39
+ @on_mouse_down = nil
40
+ @on_mouse_up = nil
41
+ @on_cursor_pos = nil
42
+ @on_mouse_wheel = nil
43
+ @on_input_char = nil
44
+ @on_input_key = nil
45
+ @on_resize = nil
46
+ @on_ime_preedit = nil
47
+ end
48
+
49
+ # =============================================================
50
+ # Frame interface — event callback registration
51
+ # =============================================================
52
+
53
+ #: () { (untyped, bool) -> void } -> void
54
+ def on_redraw(&block)
55
+ @on_redraw = block
56
+ end
57
+
58
+ #: () { (MouseEvent) -> void } -> void
59
+ def on_mouse_down(&block)
60
+ @on_mouse_down = block
61
+ end
62
+
63
+ #: () { (MouseEvent) -> void } -> void
64
+ def on_mouse_up(&block)
65
+ @on_mouse_up = block
66
+ end
67
+
68
+ #: () { (MouseEvent) -> void } -> void
69
+ def on_cursor_pos(&block)
70
+ @on_cursor_pos = block
71
+ end
72
+
73
+ #: () { (WheelEvent) -> void } -> void
74
+ def on_mouse_wheel(&block)
75
+ @on_mouse_wheel = block
76
+ end
77
+
78
+ #: () { (String) -> void } -> void
79
+ def on_input_char(&block)
80
+ @on_input_char = block
81
+ end
82
+
83
+ #: () { (Integer, Integer) -> void } -> void
84
+ def on_input_key(&block)
85
+ @on_input_key = block
86
+ end
87
+
88
+ #: () { () -> void } -> void
89
+ def on_resize(&block)
90
+ @on_resize = block
91
+ end
92
+
93
+ #: () { (String, Integer, Integer) -> void } -> void
94
+ def on_ime_preedit(&block)
95
+ @on_ime_preedit = block
96
+ end
97
+
98
+ # =============================================================
99
+ # Frame interface — queries
100
+ # =============================================================
101
+
102
+ #: () -> bool
103
+ def is_dark_mode
104
+ KonpeitoUI.is_dark_mode(@handle)
105
+ end
106
+
107
+ #: () -> NativeFrame
108
+ def get_painter
109
+ self
110
+ end
111
+
112
+ #: () -> Size
113
+ def get_size
114
+ Size.new(KonpeitoUI.get_width(@handle), KonpeitoUI.get_height(@handle))
115
+ end
116
+
117
+ #: (untyped ev) -> void
118
+ def post_update(ev)
119
+ KonpeitoUI.mark_dirty(@handle)
120
+ KonpeitoUI.request_frame(@handle)
121
+ end
122
+
123
+ # =============================================================
124
+ # Frame interface — IME / Text Input control
125
+ # =============================================================
126
+
127
+ #: () -> void
128
+ def enable_text_input
129
+ KonpeitoUI.set_text_input_enabled(@handle, true)
130
+ end
131
+
132
+ #: () -> void
133
+ def disable_text_input
134
+ KonpeitoUI.set_text_input_enabled(@handle, false)
135
+ end
136
+
137
+ #: (Integer x, Integer y, Integer w, Integer h) -> void
138
+ def set_ime_cursor_rect(x, y, w, h)
139
+ KonpeitoUI.set_text_input_rect(@handle, x.to_i, y.to_i, w.to_i, h.to_i)
140
+ end
141
+
142
+ # =============================================================
143
+ # Frame interface — clipboard
144
+ # =============================================================
145
+
146
+ #: () -> String
147
+ def get_clipboard_text
148
+ KonpeitoUI.get_clipboard_text(@handle)
149
+ end
150
+
151
+ #: (String text) -> void
152
+ def set_clipboard_text(text)
153
+ KonpeitoUI.set_clipboard_text(@handle, text)
154
+ end
155
+
156
+ # =============================================================
157
+ # Painter — drawing primitives (snake_case)
158
+ # =============================================================
159
+
160
+ #: (Integer color) -> void
161
+ def clear(color)
162
+ KonpeitoUI.clear(@handle, color)
163
+ end
164
+
165
+ #: (Float x, Float y, Float w, Float h, Integer color) -> void
166
+ def fill_rect(x, y, w, h, color)
167
+ KonpeitoUI.fill_rect(@handle, x, y, w, h, color)
168
+ end
169
+
170
+ #: (Float x, Float y, Float w, Float h, Integer color, Float sw) -> void
171
+ def stroke_rect(x, y, w, h, color, sw)
172
+ KonpeitoUI.stroke_rect(@handle, x, y, w, h, color, sw)
173
+ end
174
+
175
+ #: (Float x, Float y, Float w, Float h, Float r, Integer color) -> void
176
+ def fill_round_rect(x, y, w, h, r, color)
177
+ KonpeitoUI.fill_round_rect(@handle, x, y, w, h, r, color)
178
+ end
179
+
180
+ #: (Float x, Float y, Float w, Float h, Float r, Integer color, Float sw) -> void
181
+ def stroke_round_rect(x, y, w, h, r, color, sw)
182
+ KonpeitoUI.stroke_round_rect(@handle, x, y, w, h, r, color, sw)
183
+ end
184
+
185
+ #: (Float cx, Float cy, Float r, Integer color) -> void
186
+ def fill_circle(cx, cy, r, color)
187
+ KonpeitoUI.fill_circle(@handle, cx, cy, r, color)
188
+ end
189
+
190
+ #: (Float cx, Float cy, Float r, Integer color, Float sw) -> void
191
+ def stroke_circle(cx, cy, r, color, sw)
192
+ KonpeitoUI.stroke_circle(@handle, cx, cy, r, color, sw)
193
+ end
194
+
195
+ #: (Float x1, Float y1, Float x2, Float y2, Integer color, Float w) -> void
196
+ def draw_line(x1, y1, x2, y2, color, w)
197
+ KonpeitoUI.draw_line(@handle, x1, y1, x2, y2, color, w)
198
+ end
199
+
200
+ #: (Float cx, Float cy, Float r, Float start_angle, Float sweep_angle, Integer color) -> void
201
+ def fill_arc(cx, cy, r, start_angle, sweep_angle, color)
202
+ KonpeitoUI.fill_arc(@handle, cx, cy, r, start_angle, sweep_angle, color)
203
+ end
204
+
205
+ #: (Float cx, Float cy, Float r, Float start_angle, Float sweep_angle, Integer color, Float sw) -> void
206
+ def stroke_arc(cx, cy, r, start_angle, sweep_angle, color, sw)
207
+ KonpeitoUI.stroke_arc(@handle, cx, cy, r, start_angle, sweep_angle, color, sw)
208
+ end
209
+
210
+ #: (Float x1, Float y1, Float x2, Float y2, Integer color, Float sw, Integer dummy) -> void
211
+ def draw_polyline(x1, y1, x2, y2, color, sw, dummy)
212
+ KonpeitoUI.draw_line(@handle, x1, y1, x2, y2, color, sw)
213
+ end
214
+
215
+ #: (Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Integer color) -> void
216
+ def fill_triangle(x1, y1, x2, y2, x3, y3, color)
217
+ KonpeitoUI.fill_triangle(@handle, x1, y1, x2, y2, x3, y3, color)
218
+ end
219
+
220
+ # =============================================================
221
+ # Painter — text drawing
222
+ # draw_text supports both 6-arg (normal) and 8-arg (weight/slant)
223
+ # =============================================================
224
+
225
+ #: (String text, Float x, Float y, String font_family, Float font_size, Integer color, *untyped extra) -> void
226
+ def draw_text(text, x, y, font_family, font_size, color, *extra)
227
+ if extra.length >= 2 && (extra[0] != 0 || extra[1] != 0)
228
+ KonpeitoUI.draw_text_styled(@handle, text, x, y, font_family, font_size, color, extra[0], extra[1])
229
+ else
230
+ KonpeitoUI.draw_text(@handle, text, x, y, font_family, font_size, color)
231
+ end
232
+ end
233
+
234
+ # =============================================================
235
+ # Painter — text measurement
236
+ # =============================================================
237
+
238
+ #: (String text, String font_family, Float font_size) -> Float
239
+ def measure_text_width(text, font_family, font_size)
240
+ KonpeitoUI.measure_text_width(@handle, text, font_family, font_size)
241
+ end
242
+
243
+ #: (String font_family, Float font_size) -> Float
244
+ def measure_text_height(font_family, font_size)
245
+ KonpeitoUI.measure_text_height(@handle, font_family, font_size)
246
+ end
247
+
248
+ #: (String font_family, Float font_size) -> Float
249
+ def get_text_ascent(font_family, font_size)
250
+ KonpeitoUI.get_text_ascent(@handle, font_family, font_size)
251
+ end
252
+
253
+ # =============================================================
254
+ # Painter — path drawing
255
+ # =============================================================
256
+
257
+ #: () -> void
258
+ def begin_path
259
+ KonpeitoUI.begin_path(@handle)
260
+ end
261
+
262
+ #: (Float x, Float y) -> void
263
+ def path_move_to(x, y)
264
+ KonpeitoUI.path_move_to(@handle, x, y)
265
+ end
266
+
267
+ #: (Float x, Float y) -> void
268
+ def path_line_to(x, y)
269
+ KonpeitoUI.path_line_to(@handle, x, y)
270
+ end
271
+
272
+ #: (Integer color) -> void
273
+ def close_fill_path(color)
274
+ KonpeitoUI.close_fill_path(@handle, color)
275
+ end
276
+
277
+ #: (Integer color) -> void
278
+ def fill_path(color)
279
+ KonpeitoUI.fill_path(@handle, color)
280
+ end
281
+
282
+ # =============================================================
283
+ # Painter — canvas state
284
+ # =============================================================
285
+
286
+ #: () -> void
287
+ def save
288
+ KonpeitoUI.save(@handle)
289
+ end
290
+
291
+ #: () -> void
292
+ def restore
293
+ KonpeitoUI.restore(@handle)
294
+ end
295
+
296
+ #: (Float dx, Float dy) -> void
297
+ def translate(dx, dy)
298
+ KonpeitoUI.translate(@handle, dx, dy)
299
+ end
300
+
301
+ #: (Float x, Float y, Float w, Float h) -> void
302
+ def clip_rect(x, y, w, h)
303
+ KonpeitoUI.clip_rect(@handle, x, y, w, h)
304
+ end
305
+
306
+ # =============================================================
307
+ # Painter — image operations
308
+ # =============================================================
309
+
310
+ #: (String path) -> Integer
311
+ def load_image(path)
312
+ KonpeitoUI.load_image(@handle, path)
313
+ end
314
+
315
+ #: (String url) -> Integer
316
+ def load_net_image(url)
317
+ KonpeitoUI.load_net_image(@handle, url)
318
+ end
319
+
320
+ #: (Integer image_id, Float x, Float y, Float w, Float h) -> void
321
+ def draw_image(image_id, x, y, w, h)
322
+ KonpeitoUI.draw_image(@handle, image_id, x, y, w, h)
323
+ end
324
+
325
+ #: (Integer image_id) -> Float
326
+ def get_image_width(image_id)
327
+ KonpeitoUI.get_image_width(@handle, image_id)
328
+ end
329
+
330
+ #: (Integer image_id) -> Float
331
+ def get_image_height(image_id)
332
+ KonpeitoUI.get_image_height(@handle, image_id)
333
+ end
334
+
335
+ # =============================================================
336
+ # Painter — color utilities
337
+ # =============================================================
338
+
339
+ #: (Integer c1, Integer c2, Float t) -> Integer
340
+ def interpolate_color(c1, c2, t)
341
+ KonpeitoUI.interpolate_color(c1, c2, t)
342
+ end
343
+
344
+ #: (Integer color, Integer alpha) -> Integer
345
+ def with_alpha(color, alpha)
346
+ KonpeitoUI.with_alpha(color, alpha)
347
+ end
348
+
349
+ #: (Integer color, Float amount) -> Integer
350
+ def lighten_color(color, amount)
351
+ KonpeitoUI.lighten_color(color, amount)
352
+ end
353
+
354
+ #: (Integer color, Float amount) -> Integer
355
+ def darken_color(color, amount)
356
+ KonpeitoUI.darken_color(color, amount)
357
+ end
358
+
359
+ # =============================================================
360
+ # Painter — math helpers
361
+ # =============================================================
362
+
363
+ #: (Float radians) -> Float
364
+ def math_cos(radians)
365
+ KonpeitoUI.math_cos(radians)
366
+ end
367
+
368
+ #: (Float radians) -> Float
369
+ def math_sin(radians)
370
+ KonpeitoUI.math_sin(radians)
371
+ end
372
+
373
+ #: (Float value) -> Float
374
+ def math_sqrt(value)
375
+ KonpeitoUI.math_sqrt(value)
376
+ end
377
+
378
+ #: (Float y, Float x) -> Float
379
+ def math_atan2(y, x)
380
+ KonpeitoUI.math_atan2(y, x)
381
+ end
382
+
383
+ #: (Float value) -> Float
384
+ def math_abs(value)
385
+ KonpeitoUI.math_abs(value)
386
+ end
387
+
388
+ # =============================================================
389
+ # Painter — utilities
390
+ # =============================================================
391
+
392
+ #: () -> Integer
393
+ def current_time_millis
394
+ KonpeitoUI.current_time_millis
395
+ end
396
+
397
+ #: (Float value) -> String
398
+ def number_to_string(value)
399
+ KonpeitoUI.number_to_string(value)
400
+ end
401
+
402
+ # =============================================================
403
+ # Main loop (polling model)
404
+ # =============================================================
405
+
406
+ #: () -> void
407
+ def run
408
+ @running = true
409
+ h = @handle
410
+ redraw_cb = @on_redraw
411
+ mouse_down_cb = @on_mouse_down
412
+ mouse_up_cb = @on_mouse_up
413
+ cursor_pos_cb = @on_cursor_pos
414
+ mouse_wheel_cb = @on_mouse_wheel
415
+ input_char_cb = @on_input_char
416
+ input_key_cb = @on_input_key
417
+ resize_cb = @on_resize
418
+ ime_preedit_cb = @on_ime_preedit
419
+
420
+ while @running
421
+ # Poll SDL3 events into ring buffer
422
+ KonpeitoUI.step(h)
423
+
424
+ # Process all queued events
425
+ while KonpeitoUI.has_event(h)
426
+ evt = KonpeitoUI.event_type(h)
427
+
428
+ if evt == EVENT_QUIT
429
+ @running = false
430
+ elsif evt == EVENT_MOUSE_DOWN
431
+ if mouse_down_cb
432
+ pos = Point.new(KonpeitoUI.event_x(h), KonpeitoUI.event_y(h))
433
+ ev = MouseEvent.new(pos, KonpeitoUI.event_button(h))
434
+ mouse_down_cb.call(ev)
435
+ end
436
+ elsif evt == EVENT_MOUSE_UP
437
+ if mouse_up_cb
438
+ pos = Point.new(KonpeitoUI.event_x(h), KonpeitoUI.event_y(h))
439
+ ev = MouseEvent.new(pos, KonpeitoUI.event_button(h))
440
+ mouse_up_cb.call(ev)
441
+ end
442
+ elsif evt == EVENT_MOUSE_MOVE
443
+ if cursor_pos_cb
444
+ pos = Point.new(KonpeitoUI.event_x(h), KonpeitoUI.event_y(h))
445
+ ev = MouseEvent.new(pos, 0)
446
+ cursor_pos_cb.call(ev)
447
+ end
448
+ elsif evt == EVENT_MOUSE_WHEEL
449
+ if mouse_wheel_cb
450
+ pos = Point.new(KonpeitoUI.event_x(h), KonpeitoUI.event_y(h))
451
+ wev = WheelEvent.new(pos, KonpeitoUI.event_dy(h))
452
+ mouse_wheel_cb.call(wev)
453
+ end
454
+ elsif evt == EVENT_KEY_DOWN
455
+ if input_key_cb
456
+ input_key_cb.call(KonpeitoUI.event_key_code(h), KonpeitoUI.event_modifiers(h))
457
+ end
458
+ elsif evt == EVENT_TEXT_INPUT
459
+ if input_char_cb
460
+ input_char_cb.call(KonpeitoUI.event_text(h))
461
+ end
462
+ elsif evt == EVENT_RESIZE
463
+ resize_cb.call if resize_cb
464
+ elsif evt == EVENT_IME_PREEDIT
465
+ if ime_preedit_cb
466
+ ime_preedit_cb.call(
467
+ KonpeitoUI.event_text(h),
468
+ KonpeitoUI.event_ime_sel_start(h),
469
+ KonpeitoUI.event_ime_sel_end(h)
470
+ )
471
+ end
472
+ end
473
+
474
+ KonpeitoUI.consume_event(h)
475
+ end
476
+
477
+ # Render frame only when needed (dirty flag or frame_requested)
478
+ if KonpeitoUI.needs_redraw(h)
479
+ # Clear flags BEFORE callback — callback may set them again (e.g. animations)
480
+ KonpeitoUI.clear_dirty(h)
481
+ KonpeitoUI.clear_frame_requested(h)
482
+ KonpeitoUI.begin_frame(h)
483
+ # Pass false for completely — app.rb upgrades to true on resize/animation
484
+ redraw_cb.call(self, false) if redraw_cb
485
+ KonpeitoUI.end_frame(h)
486
+ else
487
+ # Sleep longer when idle to reduce CPU usage
488
+ sleep(0.008)
489
+ end
490
+ end
491
+
492
+ KonpeitoUI.destroy_window(h)
493
+ end
494
+ end
@@ -0,0 +1,124 @@
1
+ # Markdown AST node types and node class
2
+ # Used by MarkdownParser and MarkdownRenderer
3
+
4
+ # Node type constants
5
+ MD_DOCUMENT = 0
6
+ MD_HEADING = 1
7
+ MD_PARAGRAPH = 2
8
+ MD_TEXT = 3
9
+ MD_STRONG = 4
10
+ MD_EMPHASIS = 5
11
+ MD_CODE_INLINE = 6
12
+ MD_CODE_BLOCK = 7
13
+ MD_BLOCKQUOTE = 8
14
+ MD_LIST = 9
15
+ MD_LIST_ITEM = 10
16
+ MD_LINK = 11
17
+ MD_HORIZONTAL_RULE = 12
18
+ MD_SOFT_BREAK = 13
19
+ MD_STRIKETHROUGH = 14
20
+ MD_TABLE = 15
21
+ MD_TABLE_ROW = 16
22
+ MD_TABLE_CELL = 17
23
+ MD_IMAGE = 18
24
+ MD_MERMAID = 19
25
+
26
+ class MdNode
27
+ def initialize(type)
28
+ @type = type
29
+ @children = []
30
+ @content = ""
31
+ @level = 0
32
+ @language = ""
33
+ @href = ""
34
+ @ordered = false
35
+ @start_num = 1
36
+ @checked = -1
37
+ @align = 0
38
+ @is_header = false
39
+ end
40
+
41
+ def type
42
+ @type
43
+ end
44
+
45
+ def children
46
+ @children
47
+ end
48
+
49
+ def content
50
+ @content
51
+ end
52
+
53
+ def content=(v)
54
+ @content = v
55
+ end
56
+
57
+ def level
58
+ @level
59
+ end
60
+
61
+ def level=(v)
62
+ @level = v
63
+ end
64
+
65
+ def language
66
+ @language
67
+ end
68
+
69
+ def language=(v)
70
+ @language = v
71
+ end
72
+
73
+ def href
74
+ @href
75
+ end
76
+
77
+ def href=(v)
78
+ @href = v
79
+ end
80
+
81
+ def ordered
82
+ @ordered
83
+ end
84
+
85
+ def ordered=(v)
86
+ @ordered = v
87
+ end
88
+
89
+ def start_num
90
+ @start_num
91
+ end
92
+
93
+ def start_num=(v)
94
+ @start_num = v
95
+ end
96
+
97
+ def checked
98
+ @checked
99
+ end
100
+
101
+ def checked=(v)
102
+ @checked = v
103
+ end
104
+
105
+ def align
106
+ @align
107
+ end
108
+
109
+ def align=(v)
110
+ @align = v
111
+ end
112
+
113
+ def is_header
114
+ @is_header
115
+ end
116
+
117
+ def is_header=(v)
118
+ @is_header = v
119
+ end
120
+
121
+ def add_child(node)
122
+ @children.push(node)
123
+ end
124
+ end