hokusai-zero 0.1.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.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/Dockerfile +26 -0
  3. data/Gemfile +15 -0
  4. data/Gemfile.lock +91 -0
  5. data/LICENSE +21 -0
  6. data/README.md +28 -0
  7. data/ast/genheader +3 -0
  8. data/ast/include/hashmap.c +1151 -0
  9. data/ast/include/hashmap.c.license +20 -0
  10. data/ast/include/hashmap.h +54 -0
  11. data/ast/src/core/ast.c +448 -0
  12. data/ast/src/core/ast.h +259 -0
  13. data/ast/src/core/common.h +24 -0
  14. data/ast/src/core/component.c +85 -0
  15. data/ast/src/core/component.h +35 -0
  16. data/ast/src/core/hml.c +665 -0
  17. data/ast/src/core/hml.h +11 -0
  18. data/ast/src/core/input.c +458 -0
  19. data/ast/src/core/input.h +118 -0
  20. data/ast/src/core/style.c +101 -0
  21. data/ast/src/core/style.h +41 -0
  22. data/ast/src/core/text.c +784 -0
  23. data/ast/src/core/text.h +93 -0
  24. data/ast/src/core/util.c +140 -0
  25. data/ast/src/core/util.h +48 -0
  26. data/ast/src/hokusai.c +6 -0
  27. data/ast/src/hokusai.h +6 -0
  28. data/ast/test/fixtures/test.ui +13 -0
  29. data/ast/test/greatest.h +1266 -0
  30. data/ast/test/hokusai.c +14 -0
  31. data/ast/test/parser.c +234 -0
  32. data/ast/test/text.c +116 -0
  33. data/ext/extconf.rb +27 -0
  34. data/grammar/Cargo.lock +80 -0
  35. data/grammar/Cargo.toml +26 -0
  36. data/grammar/binding.gyp +20 -0
  37. data/grammar/bindings/node/binding.cc +28 -0
  38. data/grammar/bindings/node/index.js +19 -0
  39. data/grammar/bindings/rust/build.rs +40 -0
  40. data/grammar/bindings/rust/lib.rs +52 -0
  41. data/grammar/corpus/1_document.txt +131 -0
  42. data/grammar/corpus/2_selectors.txt +58 -0
  43. data/grammar/corpus/3_spaces.txt +69 -0
  44. data/grammar/corpus/4_errors.txt +10 -0
  45. data/grammar/corpus/5_macros.txt +175 -0
  46. data/grammar/corpus/6_styles.txt +81 -0
  47. data/grammar/grammar.js +275 -0
  48. data/grammar/package-lock.json +34 -0
  49. data/grammar/package.json +33 -0
  50. data/grammar/src/grammar.json +1269 -0
  51. data/grammar/src/node-types.json +474 -0
  52. data/grammar/src/parser.c +5772 -0
  53. data/grammar/src/scanner.c +258 -0
  54. data/grammar/src/tree_sitter/parser.h +230 -0
  55. data/grammar/src/tree_sitter/scanner.h +12 -0
  56. data/grammar/test.nml +10 -0
  57. data/hokusai.gemspec +19 -0
  58. data/ui/examples/assets/DigitalDisplay.ttf +0 -0
  59. data/ui/examples/assets/OpenSans-Regular.ttf +0 -0
  60. data/ui/examples/assets/addy.png +0 -0
  61. data/ui/examples/assets/baby_sean.png +0 -0
  62. data/ui/examples/assets/football-troll.png +0 -0
  63. data/ui/examples/assets/gear.png +0 -0
  64. data/ui/examples/assets/icecold.ttf +0 -0
  65. data/ui/examples/assets/science-troll.png +0 -0
  66. data/ui/examples/buddy.rb +31 -0
  67. data/ui/examples/clock.rb +58 -0
  68. data/ui/examples/counter.rb +123 -0
  69. data/ui/examples/dynamic.rb +147 -0
  70. data/ui/examples/foobar.rb +236 -0
  71. data/ui/examples/stock.rb +115 -0
  72. data/ui/examples/stock_decider/option.rb +74 -0
  73. data/ui/examples/tic_tac_toe.rb +246 -0
  74. data/ui/lib/lib_hokusai.rb +425 -0
  75. data/ui/spec/hokusai/ast_spec.rb +88 -0
  76. data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +50 -0
  77. data/ui/spec/hokusai/automation/selector_spec.rb +68 -0
  78. data/ui/spec/hokusai/block_spec.rb +126 -0
  79. data/ui/spec/hokusai/directives_spec.rb +327 -0
  80. data/ui/spec/hokusai/e2e/client_spec.rb +58 -0
  81. data/ui/spec/hokusai/e2e/meta_spec.rb +42 -0
  82. data/ui/spec/hokusai/publisher_spec.rb +38 -0
  83. data/ui/spec/hokusai/slots_spec.rb +150 -0
  84. data/ui/spec/hokusai/util/piece_table_spec.rb +90 -0
  85. data/ui/spec/hokusai_spec.rb +0 -0
  86. data/ui/spec/spec_helper.rb +30 -0
  87. data/ui/src/hokusai/ast.rb +446 -0
  88. data/ui/src/hokusai/automation/client.rb +167 -0
  89. data/ui/src/hokusai/automation/constants.rb +98 -0
  90. data/ui/src/hokusai/automation/converters/selector_converter.rb +61 -0
  91. data/ui/src/hokusai/automation/driver.rb +54 -0
  92. data/ui/src/hokusai/automation/driver_command_queue.rb +50 -0
  93. data/ui/src/hokusai/automation/driver_commands/base.rb +79 -0
  94. data/ui/src/hokusai/automation/driver_commands/get_attribute.rb +41 -0
  95. data/ui/src/hokusai/automation/driver_commands/invoke.rb +33 -0
  96. data/ui/src/hokusai/automation/driver_commands/locate.rb +48 -0
  97. data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +94 -0
  98. data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +213 -0
  99. data/ui/src/hokusai/automation/keys_transcoder.rb +128 -0
  100. data/ui/src/hokusai/automation/selector.rb +39 -0
  101. data/ui/src/hokusai/automation/server.rb +114 -0
  102. data/ui/src/hokusai/automation.rb +3 -0
  103. data/ui/src/hokusai/backends/raylib/config.rb +47 -0
  104. data/ui/src/hokusai/backends/raylib/font.rb +113 -0
  105. data/ui/src/hokusai/backends/raylib/keys.rb +124 -0
  106. data/ui/src/hokusai/backends/raylib.rb +449 -0
  107. data/ui/src/hokusai/backends/sdl2/Monaco.ttf +0 -0
  108. data/ui/src/hokusai/backends/sdl2/color.rb +12 -0
  109. data/ui/src/hokusai/backends/sdl2/config.rb +31 -0
  110. data/ui/src/hokusai/backends/sdl2/font.rb +127 -0
  111. data/ui/src/hokusai/backends/sdl2/keys.rb +119 -0
  112. data/ui/src/hokusai/backends/sdl2.rb +529 -0
  113. data/ui/src/hokusai/block.rb +237 -0
  114. data/ui/src/hokusai/blocks/button.rb +100 -0
  115. data/ui/src/hokusai/blocks/checkbox.rb +51 -0
  116. data/ui/src/hokusai/blocks/circle.rb +28 -0
  117. data/ui/src/hokusai/blocks/clipped.rb +23 -0
  118. data/ui/src/hokusai/blocks/cursor.rb +49 -0
  119. data/ui/src/hokusai/blocks/dynamic.rb +37 -0
  120. data/ui/src/hokusai/blocks/empty.rb +10 -0
  121. data/ui/src/hokusai/blocks/hblock.rb +35 -0
  122. data/ui/src/hokusai/blocks/image.rb +18 -0
  123. data/ui/src/hokusai/blocks/input.rb +200 -0
  124. data/ui/src/hokusai/blocks/label.rb +39 -0
  125. data/ui/src/hokusai/blocks/panel.rb +126 -0
  126. data/ui/src/hokusai/blocks/rect.rb +24 -0
  127. data/ui/src/hokusai/blocks/scissor_begin.rb +18 -0
  128. data/ui/src/hokusai/blocks/scissor_end.rb +12 -0
  129. data/ui/src/hokusai/blocks/scrollbar.rb +103 -0
  130. data/ui/src/hokusai/blocks/selectable.rb +77 -0
  131. data/ui/src/hokusai/blocks/svg.rb +20 -0
  132. data/ui/src/hokusai/blocks/text.rb +214 -0
  133. data/ui/src/hokusai/blocks/titlebar/osx.rb +145 -0
  134. data/ui/src/hokusai/blocks/toggle.rb +55 -0
  135. data/ui/src/hokusai/blocks/vblock.rb +35 -0
  136. data/ui/src/hokusai/commands/base.rb +22 -0
  137. data/ui/src/hokusai/commands/circle.rb +47 -0
  138. data/ui/src/hokusai/commands/image.rb +45 -0
  139. data/ui/src/hokusai/commands/rect.rb +158 -0
  140. data/ui/src/hokusai/commands/scissor.rb +22 -0
  141. data/ui/src/hokusai/commands/text.rb +92 -0
  142. data/ui/src/hokusai/commands.rb +87 -0
  143. data/ui/src/hokusai/diff.rb +124 -0
  144. data/ui/src/hokusai/error.rb +3 -0
  145. data/ui/src/hokusai/event.rb +54 -0
  146. data/ui/src/hokusai/events/keyboard.rb +84 -0
  147. data/ui/src/hokusai/events/mouse.rb +172 -0
  148. data/ui/src/hokusai/font.rb +280 -0
  149. data/ui/src/hokusai/meta.rb +152 -0
  150. data/ui/src/hokusai/mounting/loop_entry.rb +230 -0
  151. data/ui/src/hokusai/mounting/mount_entry.rb +74 -0
  152. data/ui/src/hokusai/mounting/update_entry.rb +101 -0
  153. data/ui/src/hokusai/node.rb +98 -0
  154. data/ui/src/hokusai/node_mounter.rb +102 -0
  155. data/ui/src/hokusai/painter.rb +214 -0
  156. data/ui/src/hokusai/publisher.rb +32 -0
  157. data/ui/src/hokusai/style.rb +72 -0
  158. data/ui/src/hokusai/types.rb +266 -0
  159. data/ui/src/hokusai/util/clamping_iterator.rb +202 -0
  160. data/ui/src/hokusai/util/piece_table.rb +111 -0
  161. data/ui/src/hokusai/util/selection.rb +145 -0
  162. data/ui/src/hokusai.rb +120 -0
  163. data/ui/vendor/.gitkeep +0 -0
  164. data/vendor/.gitkeep +0 -0
  165. data/xmake.lua +192 -0
  166. metadata +222 -0
@@ -0,0 +1,128 @@
1
+ module Hokusai::Automation
2
+ module KeysTranscoder
3
+ KEYS = {
4
+ shift: "\ue008",
5
+ ctrl: "\ue009",
6
+ alt: "\ue00A",
7
+ super: "\ue03D",
8
+ lshift: "\ue008",
9
+ lctrl: "\ue009",
10
+ lalt: "\ue00A",
11
+ lsuper: "\ue03D",
12
+ rshift: "\ue050",
13
+ rctrl: "\ue051",
14
+ ralt: "\ue052",
15
+ rsuper: "\ue053",
16
+ enter: "\ue007",
17
+ tab: "\ue004",
18
+ backspace: "\ue003",
19
+ insert: "\ue016",
20
+ delete: "\ue017",
21
+ up: "\ue013",
22
+ right: "\ue014",
23
+ down: "\ue015",
24
+ left: "\ue012",
25
+ page_up: "\ue00E",
26
+ page_down: "\ue00F",
27
+ end: "\ue010",
28
+ home: "\ue011",
29
+ pause: "\ue00B",
30
+ escape: "\ue00C",
31
+ null: "\ue000",
32
+ cancel: "\ue001",
33
+ f1: "\ue031",
34
+ f2: "\ue032",
35
+ f3: "\ue033",
36
+ f4: "\ue034",
37
+ f5: "\ue035",
38
+ f6: "\ue036",
39
+ f7: "\ue037",
40
+ f8: "\ue038",
41
+ f9: "\ue039",
42
+ f10: "\ue03A",
43
+ f11: "\ue03B",
44
+ f12: "\ue03C",
45
+ kp0: "\ue01A",
46
+ kp1: "\ue01B",
47
+ kp2: "\ue01C",
48
+ kp3: "\ue01D",
49
+ kp4: "\ue01E",
50
+ kp5: "\ue01F",
51
+ kp6: "\ue020",
52
+ kp7: "\ue021",
53
+ kp8: "\ue022",
54
+ kp9: "\ue023",
55
+ multiply: "\ue024",
56
+ add: "\ue025",
57
+ separator: "\ue026",
58
+ subtract: "\ue027",
59
+ decimal: "\ue028",
60
+ divide: "\ue029",
61
+ equal: "\ue019",
62
+ caps_lock: "\ue054",
63
+ scroll_lock: "\ue055",
64
+ num_lock: "\ue056",
65
+ print_screen: "\ue057",
66
+ kb_menu: "\ue058",
67
+ back: "\ue059",
68
+ menu: "\ue05A",
69
+ volume_up: "\ue05B",
70
+ volume_down: "\ue05C",
71
+ }
72
+
73
+ REVERSE_KEYS = KEYS.invert
74
+
75
+ def self.[](key)
76
+ return KEYS[key] if KEYS[key]
77
+
78
+ raise Hokusai::Automation::Error.new("Unsupported key: #{key}")
79
+ end
80
+
81
+ def self.decode(str)
82
+ parts = str.split("")
83
+ keys = []
84
+ prog = []
85
+
86
+ while part = parts.shift
87
+
88
+ if key = REVERSE_KEYS[part]
89
+ if key == :null
90
+ keys << prog
91
+ prog = []
92
+ else
93
+ prog << key
94
+ end
95
+ else
96
+ prog << part.to_s
97
+ end
98
+ end
99
+
100
+ keys.concat prog
101
+ keys
102
+ end
103
+
104
+ def self.encode(keys)
105
+ keys.map { |key| encode_key(key) }.join("")
106
+ end
107
+
108
+ def self.encode_key(key)
109
+ case key
110
+ when Symbol
111
+ self[key]
112
+ when Array
113
+ key = key.map do |e|
114
+ if e.is_a?(Symbol)
115
+ self[e]
116
+ else
117
+ e
118
+ end
119
+ end
120
+
121
+ key << self[:null]
122
+ key.join("")
123
+ else
124
+ key.to_s
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,39 @@
1
+ module Hokusai::Automation
2
+ class Selector
3
+ attr_reader :node, :id, :class_list
4
+
5
+ def initialize(node, id, classes)
6
+ @node = node
7
+ @id = id
8
+ @class_list = classes || []
9
+ end
10
+
11
+ def matches(block)
12
+ if portal = block.node.portal
13
+ ast = portal.ast
14
+
15
+ matches = [[ast.type, node], [ast.id, id]].reduce(true) do |memo, (ast_property, target)|
16
+ next memo if target.nil?
17
+
18
+ target == ast_property && memo
19
+ end
20
+
21
+ return (class_list & ast.classes) == class_list && matches
22
+ end
23
+
24
+ false
25
+ end
26
+
27
+ def to_s(str = "")
28
+ classes_string = nil
29
+
30
+ unless class_list.empty?
31
+ classes_string = ".#{class_list.join(".")}"
32
+
33
+ str << "#{node || ""}##{id || ""}#{classes_string || ""}"
34
+ end
35
+
36
+ str
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+ require "thin"
5
+ require "ostruct"
6
+ require_relative "./driver"
7
+ require_relative "./constants"
8
+
9
+ module Hokusai
10
+ module Automation
11
+ class App
12
+ attr_reader :driver
13
+
14
+ def self.queue
15
+ @queue ||= {}
16
+ end
17
+
18
+ def initialize(driver)
19
+ @driver = driver
20
+ end
21
+
22
+ ROUTES = [
23
+ ["/commands/locate", DriverCommands::Locate],
24
+ ["/commands/invoke", DriverCommands::Invoke],
25
+ ["/commands/attribute", DriverCommands::GetAttribute],
26
+ ["/commands/click", DriverCommands::TriggerMouseClick],
27
+ ["/commands/drag", DriverCommands::TriggerMouseDrag],
28
+ ["/commands/hover", DriverCommands::TriggerMouseHover],
29
+ ["/commands/mousemove", DriverCommands::TriggerMouseMove],
30
+ ["/commands/mousewheel", DriverCommands::TriggerMouseWheel],
31
+ ["/commands/keyboard", DriverCommands::TriggerKeyboard]
32
+ ].to_h
33
+
34
+ def call(env)
35
+ request = Rack::Request.new(env)
36
+
37
+ unless request.post?
38
+ return respond(404, "Not Found", {})
39
+ end
40
+
41
+ return respond(200, "") if request.path == "/ready"
42
+
43
+ if command_klass = ROUTES[request.path]
44
+ json = JSON.parse(request.body.string, symbolize_names: true)
45
+ command = command_klass.new(json)
46
+ driver.execute(command)
47
+
48
+ Log.debug { "Pushed #{command.class} command #{driver.queue.commands}" }
49
+
50
+ poll(command.request_id)
51
+ else
52
+ respond(403, "Bad Request", {})
53
+ end
54
+ end
55
+
56
+ def poll(request_id)
57
+ poll_timeout = 2
58
+ poll_interval = 0.02
59
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
60
+
61
+ while (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) < poll_timeout
62
+ begin
63
+ if payload = driver.results[request_id]
64
+ driver.results.delete(request_id)
65
+
66
+ _, value = payload
67
+
68
+ Log.debug { "request id found! sending payload #{value}" }
69
+
70
+ if value.is_a?(Automation::Error)
71
+ message = value.message || "Something went wrong"
72
+
73
+ return respond(500, "Error occurred: #{message}" , {"Content-Type" => "text/plain"})
74
+ else
75
+ return respond(200, {"value" => value}.to_json)
76
+ end
77
+ end
78
+
79
+ sleep poll_interval
80
+ rescue ex
81
+ respond(500, "Error occurred while processing command: #{ex.message}", {"Content-Type" => "text/plain"})
82
+ end
83
+ end
84
+
85
+ respond(408, "Timeout", {"Content-Type" => "text/plain"})
86
+ end
87
+
88
+ def parse_body(request)
89
+ JSON.parse(request.body, symbolize_names: true) unless request.body.nil?
90
+ end
91
+
92
+ def respond(status, message, headers = {"Content-Type" => "application/json"})
93
+ [status, headers, message]
94
+ end
95
+ end
96
+
97
+ class Server
98
+ def self.start(*args, driver: Hokusai::Automation::Driver.new)
99
+ app = App.new(driver)
100
+
101
+ @socket = Thin::Server.new(*args, app)
102
+ Hokusai::ThreadPool.post do
103
+ @socket.start
104
+ end
105
+ end
106
+
107
+ def self.stop
108
+ @socket.stop
109
+
110
+ Hokusai::ThreadPool.prune_pool
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,3 @@
1
+ require "colorize"
2
+ require_relative "./automation/server"
3
+ require_relative "./automation/client"
@@ -0,0 +1,47 @@
1
+ module Hokusai::Backends
2
+ class RaylibBackend::ConfigError < StandardError; end
3
+
4
+ class RaylibBackend::Config
5
+ attr_accessor :width, :height, :fps,
6
+ :title, :config_flags, :window_state_flags,
7
+ :automation_driver, :background, :after_load_cb,
8
+ :host, :port, :automated, :on_reload, :event_waiting
9
+
10
+ def initialize
11
+ @width = 500
12
+ @height = 500
13
+ @fps = 60
14
+ @title = "(Unknown Title)"
15
+ @config_flags = Raylib::FLAG_WINDOW_RESIZABLE | Raylib::FLAG_VSYNC_HINT
16
+ @window_state_flags = Raylib::FLAG_WINDOW_RESIZABLE
17
+ @automation_driver = nil
18
+ @background = Raylib::WHITE
19
+ @after_load_cb = nil
20
+ @host = "127.0.0.1"
21
+ @port = 4333
22
+ @automated = false
23
+ @on_reload = ->(_){}
24
+ @event_waiting = false
25
+ end
26
+
27
+ def start_automation_driver
28
+ raise ConfigError.new("Need a Hokusai::Driver in order to automate") if automation_driver.nil?
29
+
30
+ automation_driver.serve(host, port)
31
+ end
32
+
33
+ def automate(host, port)
34
+ self.host = host
35
+ self.port = port
36
+ self.automated = true
37
+ end
38
+
39
+ def after_load(&block)
40
+ self.after_load_cb = block
41
+ end
42
+
43
+ def on_reload(&block)
44
+ @on_reload = block
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,113 @@
1
+ module Hokusai
2
+ module Backends
3
+ class RaylibBackend
4
+ class DataForCb < FFI::Struct
5
+ layout :size, :int,
6
+ :spacing, :int,
7
+ :raw, :pointer
8
+
9
+ def self.create(size, spacing, raw)
10
+ obj = new.tap do |instance|
11
+ instance[:size] = size
12
+ instance[:spacing] = spacing
13
+ instance[:raw] = raw
14
+ end
15
+
16
+ yield obj.to_ptr
17
+ end
18
+ end
19
+
20
+ OnWidthCb = Proc.new do |char, ffi_pointer|
21
+ data = DataForCb.new ffi_pointer
22
+
23
+ Raylib.MeasureTextEx(data[:raw], "#{char.chr}", data[:size], data[:spacing]).x + data[:spacing]
24
+ end
25
+
26
+ class Font < Hokusai::Font
27
+ attr_reader :raw
28
+
29
+ DEFAULT = "–—‘’“”…\r\n\t0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%%^&*(),.?/\"\\[]-_=+|~`{}<>;:'\0"
30
+
31
+ def self.default
32
+ font = Raylib.GetFontDefault
33
+ Raylib.SetTextureFilter(font.texture, Raylib::TEXTURE_FILTER_BILINEAR)
34
+ Raylib.GenTextureMipmaps(font.texture)
35
+
36
+ new(font)
37
+ end
38
+
39
+ def self.from(file)
40
+ font = Raylib.LoadFont(file)
41
+ Raylib.SetTextureFilter(font.texture, Raylib::TEXTURE_FILTER_BILINEAR)
42
+ Raylib.GenTextureMipmaps(font.texture)
43
+
44
+ new(font)
45
+ end
46
+
47
+ def self.from_ext(file, font_size, codepoint_string = DEFAULT)
48
+ ptr = FFI::MemoryPointer.new :int
49
+ codepoints = Raylib.LoadCodepoints(codepoint_string, ptr)
50
+ count = ptr.read_int
51
+
52
+ raylib_font = Raylib.LoadFontEx(file, font_size, codepoints, count)
53
+ Raylib.GenTextureMipmaps(raylib_font.texture)
54
+ Raylib.SetTextureFilter(raylib_font.texture, Raylib::TEXTURE_FILTER_BILINEAR)
55
+
56
+ font = new(raylib_font)
57
+ Raylib.UnloadCodepoints(codepoints)
58
+
59
+ font
60
+ end
61
+
62
+ def initialize(raw, spacing = 1.0)
63
+ @raw = raw
64
+ @spacing = spacing
65
+ end
66
+
67
+ # returns the spacing for this font
68
+ # based on the text size
69
+ def spacing
70
+ ssize = raw.baseSize || 1
71
+ ssize = 10 if ssize < 10
72
+
73
+ (ssize / (raw.baseSize.zero? ? 1 : raw.baseSize)).to_f
74
+ end
75
+
76
+ def measure(string, size)
77
+ vec = Raylib.MeasureTextEx(raw, string, size, spacing)
78
+
79
+ [vec.x, vec.y]
80
+ end
81
+
82
+ def height
83
+ raw.baseSize
84
+ end
85
+
86
+
87
+ def clamp_markdown(text, size, width, initial_offset = 0.0)
88
+ clamping_pointer = FFI::MemoryPointer.new :pointer
89
+ RaylibBackend::DataForCb.create(size, spacing, raw) do |ptr|
90
+ ret = LibHokusai.hoku_text_md_clamp(clamping_pointer, text, width, initial_offset, ptr, RaylibBackend::OnWidthCb)
91
+ raise Hokusai::Error.new("Clamping failed") unless ret.zero?
92
+ end
93
+
94
+ clamping = LibHokusai::HokuClamping.new(FFI::AutoPointer.new(clamping_pointer.get_pointer(0), LibHokusai.method(:hoku_text_clamping_free)))
95
+
96
+ Hokusai::Clamping.new(clamping, markdown: true)
97
+ end
98
+
99
+ def clamp(text, size, width, initial_offset = 0.0)
100
+ clamping_pointer = FFI::MemoryPointer.new :pointer
101
+ RaylibBackend::DataForCb.create(size, spacing, raw) do |ptr|
102
+ ret = LibHokusai.hoku_text_clamp(clamping_pointer, text, width, initial_offset, ptr, RaylibBackend::OnWidthCb)
103
+ raise Hokusai::Error.new("Clamping failed") unless ret.zero?
104
+ end
105
+
106
+ clamping = LibHokusai::HokuClamping.new(FFI::AutoPointer.new(clamping_pointer.get_pointer(0), LibHokusai.method(:hoku_text_clamping_free)))
107
+
108
+ Hokusai::Clamping.new(clamping)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,124 @@
1
+ module Hokusai::Backends
2
+ class RaylibBackend
3
+ Keys = [
4
+ [:null, Raylib::KEY_NULL],
5
+ [:left_shift, Raylib::KEY_LEFT_SHIFT],
6
+ [:left_control, Raylib::KEY_LEFT_CONTROL],
7
+ [:left_alt, Raylib::KEY_LEFT_ALT],
8
+ [:left_super, Raylib::KEY_LEFT_SUPER],
9
+ [:right_shift, Raylib::KEY_RIGHT_SHIFT],
10
+ [:right_control, Raylib::KEY_RIGHT_CONTROL],
11
+ [:right_alt, Raylib::KEY_RIGHT_ALT],
12
+ [:right_super, Raylib::KEY_RIGHT_SUPER],
13
+ [:apostrophe, Raylib::KEY_APOSTROPHE],
14
+ [:comma, Raylib::KEY_COMMA],
15
+ [:minus, Raylib::KEY_MINUS],
16
+ [:period, Raylib::KEY_PERIOD],
17
+ [:slash, Raylib::KEY_SLASH],
18
+ [:zero, Raylib::KEY_ZERO],
19
+ [:one, Raylib::KEY_ONE],
20
+ [:two, Raylib::KEY_TWO],
21
+ [:three, Raylib::KEY_THREE],
22
+ [:four, Raylib::KEY_FOUR],
23
+ [:five, Raylib::KEY_FIVE],
24
+ [:six, Raylib::KEY_SIX],
25
+ [:seven, Raylib::KEY_SEVEN],
26
+ [:eight, Raylib::KEY_EIGHT],
27
+ [:nine, Raylib::KEY_NINE],
28
+ [:semicolon, Raylib::KEY_SEMICOLON],
29
+ [:equal, Raylib::KEY_EQUAL],
30
+ [:a, Raylib::KEY_A],
31
+ [:b, Raylib::KEY_B],
32
+ [:c, Raylib::KEY_C],
33
+ [:d, Raylib::KEY_D],
34
+ [:e, Raylib::KEY_E],
35
+ [:f, Raylib::KEY_F],
36
+ [:g, Raylib::KEY_G],
37
+ [:h, Raylib::KEY_H],
38
+ [:i, Raylib::KEY_I],
39
+ [:j, Raylib::KEY_J],
40
+ [:k, Raylib::KEY_K],
41
+ [:l, Raylib::KEY_L],
42
+ [:m, Raylib::KEY_M],
43
+ [:n, Raylib::KEY_N],
44
+ [:o, Raylib::KEY_O],
45
+ [:p, Raylib::KEY_P],
46
+ [:q, Raylib::KEY_Q],
47
+ [:r, Raylib::KEY_R],
48
+ [:s, Raylib::KEY_S],
49
+ [:t, Raylib::KEY_T],
50
+ [:u, Raylib::KEY_U],
51
+ [:v, Raylib::KEY_V],
52
+ [:w, Raylib::KEY_W],
53
+ [:x, Raylib::KEY_X],
54
+ [:y, Raylib::KEY_Y],
55
+ [:z, Raylib::KEY_Z],
56
+ [:left_bracket, Raylib::KEY_LEFT_BRACKET],
57
+ [:backslash, Raylib::KEY_BACKSLASH],
58
+ [:right_bracket, Raylib::KEY_RIGHT_BRACKET],
59
+ [:grave, Raylib::KEY_GRAVE],
60
+ [:space, Raylib::KEY_SPACE],
61
+ [:escape, Raylib::KEY_ESCAPE],
62
+ [:enter, Raylib::KEY_ENTER],
63
+ [:tab, Raylib::KEY_TAB],
64
+ [:backspace, Raylib::KEY_BACKSPACE],
65
+ [:insert, Raylib::KEY_INSERT],
66
+ [:delete, Raylib::KEY_DELETE],
67
+ [:right, Raylib::KEY_RIGHT],
68
+ [:left, Raylib::KEY_LEFT],
69
+ [:down, Raylib::KEY_DOWN],
70
+ [:up, Raylib::KEY_UP],
71
+ [:page_up, Raylib::KEY_PAGE_UP],
72
+ [:page_down, Raylib::KEY_PAGE_DOWN],
73
+ [:home, Raylib::KEY_HOME],
74
+ [:end, Raylib::KEY_END],
75
+ [:caps_lock, Raylib::KEY_CAPS_LOCK],
76
+ [:scroll_lock, Raylib::KEY_SCROLL_LOCK],
77
+ [:num_lock, Raylib::KEY_NUM_LOCK],
78
+ [:print_screen, Raylib::KEY_PRINT_SCREEN],
79
+ [:pause, Raylib::KEY_PAUSE],
80
+ [:f1, Raylib::KEY_F1],
81
+ [:f2, Raylib::KEY_F2],
82
+ [:f3, Raylib::KEY_F3],
83
+ [:f4, Raylib::KEY_F4],
84
+ [:f5, Raylib::KEY_F5],
85
+ [:f6, Raylib::KEY_F6],
86
+ [:f7, Raylib::KEY_F7],
87
+ [:f8, Raylib::KEY_F8],
88
+ [:f9, Raylib::KEY_F9],
89
+ [:f10, Raylib::KEY_F10],
90
+ [:f11, Raylib::KEY_F11],
91
+ [:f12, Raylib::KEY_F12],
92
+ [:left_shift, Raylib::KEY_LEFT_SHIFT],
93
+ [:left_control, Raylib::KEY_LEFT_CONTROL],
94
+ [:left_alt, Raylib::KEY_LEFT_ALT],
95
+ [:left_super, Raylib::KEY_LEFT_SUPER],
96
+ [:right_shift, Raylib::KEY_RIGHT_SHIFT],
97
+ [:right_control, Raylib::KEY_RIGHT_CONTROL],
98
+ [:right_alt, Raylib::KEY_RIGHT_ALT],
99
+ [:right_super, Raylib::KEY_RIGHT_SUPER],
100
+ [:kb_menu, Raylib::KEY_KB_MENU],
101
+ [:kp_0, Raylib::KEY_KP_0],
102
+ [:kp_1, Raylib::KEY_KP_1],
103
+ [:kp_2, Raylib::KEY_KP_2],
104
+ [:kp_3, Raylib::KEY_KP_3],
105
+ [:kp_4, Raylib::KEY_KP_4],
106
+ [:kp_5, Raylib::KEY_KP_5],
107
+ [:kp_6, Raylib::KEY_KP_6],
108
+ [:kp_7, Raylib::KEY_KP_7],
109
+ [:kp_8, Raylib::KEY_KP_8],
110
+ [:kp_9, Raylib::KEY_KP_9],
111
+ [:kp_decimal, Raylib::KEY_KP_DECIMAL],
112
+ [:kp_divide, Raylib::KEY_KP_DIVIDE],
113
+ [:kp_multiply, Raylib::KEY_KP_MULTIPLY],
114
+ [:kp_subtract, Raylib::KEY_KP_SUBTRACT],
115
+ [:kp_add, Raylib::KEY_KP_ADD],
116
+ [:kp_enter, Raylib::KEY_KP_ENTER],
117
+ [:kp_equal, Raylib::KEY_KP_EQUAL],
118
+ [:back, Raylib::KEY_BACK],
119
+ [:menu, Raylib::KEY_MENU],
120
+ [:volume_up, Raylib::KEY_VOLUME_UP],
121
+ [:volume_down, Raylib::KEY_VOLUME_DOWN]]
122
+ end
123
+ end
124
+