libui 0.0.4.alpha → 0.0.5.alpha

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: a74f99e290fdd8cddcd933eea2a41dd3ca6949c385feb496f3991df6cdbc730f
4
- data.tar.gz: d329a9c983c42281a4897f91c84c562a200d231b75dd8f7bee44763b3c719ad8
3
+ metadata.gz: 9942c95097af2b3c542472fa3e144e040cf3f9c0ef253e891d87b79b93070e77
4
+ data.tar.gz: a69a733f1cd1dd2274c601422a2cb3a5b91d762055d73fc3e9e9f59e6f11c919
5
5
  SHA512:
6
- metadata.gz: 715cd016369cce7a28b4f4789f3b42fbe383b13d97c7bd8debda929cabefba2672487c5ecbdef8f9b621fae22228e17c39914de3c99b67da659b6a6fd0b976bf
7
- data.tar.gz: 7271aad7f11b22d39f82ef693d3e0be914cf6c33e851872b6b0eef6e080890f7854192dcb104550de6f0e626b5793c916caf3d415618084b86dd4a987bc9754d
6
+ metadata.gz: 47d42cfbc47996ad411f0ba9e6634378fa2bd088d84bc4179698c4ad3c049a7ce8e75218c8fd93538362d01961c9ca4d278aa2c60a5074a1fea532d4b22841b8
7
+ data.tar.gz: 25c390450f42ff51ee05a9f5c7c9409c16860ac1ae3351e0d85aa30ad1d753f7cad2e1091ff9193bdf85cb21d77c344fbe1acdb5e429746e9d69574b59388379
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # libui
2
+
3
+ ![build](https://github.com/kojix2/libui/workflows/build/badge.svg)
2
4
  [![Gem Version](https://badge.fury.io/rb/libui.svg)](https://badge.fury.io/rb/libui)
3
5
 
4
- [libui](https://github.com/andlabs/libui) - a portable GUI library -for Ruby
6
+ :radio_button: [libui](https://github.com/andlabs/libui) - a portable GUI library -for Ruby
5
7
 
6
8
  ## Installation
7
9
 
@@ -9,6 +11,8 @@
9
11
  gem install libui --pre
10
12
  ```
11
13
 
14
+ The libui gem package contains the official release of the libui shared library version 4.1 for Windows, Mac, and Linux.
15
+
12
16
  ## Usage
13
17
 
14
18
  See [examples](https://github.com/kojix2/libui/tree/main/examples) directory.
@@ -9,31 +9,68 @@ module LibUI
9
9
  attr_accessor :ffi_lib
10
10
  end
11
11
 
12
- self.ffi_lib = case RbConfig::CONFIG['host_os']
13
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
14
- # File.expand_path("libui.dll", ENV['LIBUIDIR'])
15
- File.expand_path('../vendor/libui.dll', __dir__)
16
- when /darwin|mac os/
17
- # File.expand_path("libui.dylib", ENV['LIBUIDIR'])
18
- File.expand_path('../vendor/libui.dylib', __dir__)
19
- else # TODO: Mac
20
- # File.expand_path("libui.so", ENV['LIBUIDIR'])
21
- File.expand_path('../vendor/libui.so', __dir__)
12
+ lib_name = case RbConfig::CONFIG['host_os']
13
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
14
+ 'libui.dll'
15
+ when /darwin|mac os/
16
+ 'libui.dylib'
17
+ else
18
+ 'libui.so'
19
+ end
20
+
21
+ self.ffi_lib = if ENV['LIBUIDIR'] && !ENV['LIBUIDIR'].empty?
22
+ File.expand_path(lib_name, ENV['LIBUIDIR'])
23
+ else
24
+ File.expand_path("../vendor/#{lib_name}", __dir__)
22
25
  end
23
26
 
24
27
  require_relative 'libui/ffi'
25
28
 
26
29
  class << self
27
- FFI.ffi_methods.each do |original_method_name|
30
+ FFI.func_map.each_key do |original_method_name|
31
+ # Convert snake_case to CamelCase.
28
32
  name = original_method_name.delete_prefix('ui')
29
33
  .gsub(/::/, '/')
30
34
  .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
31
35
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
32
36
  .tr('-', '_')
33
37
  .downcase
34
- define_method(name) do |*args|
38
+
39
+ func = FFI.func_map[original_method_name]
40
+
41
+ define_method(name) do |*args, &blk|
42
+ # Assume that block is the last argument.
43
+ args << blk if blk
44
+
45
+ # The proc object is converted to a Closure::BlockCaller object.
46
+ args.map!.with_index do |arg, idx|
47
+ if arg.is_a?(Proc)
48
+ # The types of the function arguments are recorded beforehand.
49
+ # See the monkey patch in ffi.rb.
50
+ Fiddle::Closure::BlockCaller.new(*func.inner_functions[idx][1..2], &arg)
51
+ else
52
+ arg
53
+ end
54
+ end
55
+
56
+ # Make it possible to omit the last nil. This may be an over-optimization.
57
+ siz = func.argtype.size - 1
58
+ args[siz] = nil if args.size == siz
59
+
35
60
  FFI.public_send(original_method_name, *args)
36
61
  end
37
62
  end
63
+
64
+ module CustomMethods
65
+ def init(opt = FFI::InitOptions.malloc)
66
+ i = super(opt)
67
+ unless i.size.zero?
68
+ warn 'error'
69
+ warn UI.free_init_error(init)
70
+ end
71
+ end
72
+ end
73
+
74
+ prepend CustomMethods
38
75
  end
39
76
  end
@@ -2,6 +2,81 @@
2
2
 
3
3
  require 'fiddle/import'
4
4
 
5
+ module Fiddle
6
+ # Change the Function to hold a little more information.
7
+ # FIXME: Give inner_function a better name.
8
+ class Function
9
+ attr_accessor :inner_functions, :argtype
10
+ end
11
+
12
+ module Importer
13
+ def parse_signature(signature, tymap = nil)
14
+ tymap ||= {}
15
+ ret, func, args = split_signature(signature)
16
+ symname = func
17
+ ctype = parse_ctype(ret, tymap)
18
+ inner_funcs = [] # Added
19
+ argtype = split_arguments(args).collect.with_index do |arg, idx| # Added with_index
20
+ # Check if it is a function pointer or not
21
+ if arg =~ /\(\*.*\)\(.*\)/ # Added
22
+ # From the arguments, create a notation that looks like a function declaration
23
+ # int(*f)(int *, void *) -> int f(int *, void *)
24
+ func_arg = arg.sub('(*', ' ').sub(')', '') # Added
25
+ # Use Fiddle's parse_signature method again.
26
+ inner_funcs[idx] = parse_signature(func_arg) # Added
27
+ end # Added
28
+ parse_ctype(arg, tymap)
29
+ end
30
+ # Added inner_funcs. Original method return only 3 values.
31
+ [symname, ctype, argtype, inner_funcs]
32
+ end
33
+
34
+ # refactored
35
+ def split_signature(signature)
36
+ case compact(signature)
37
+ when /^(?:[\w*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/
38
+ func = Regexp.last_match(1)
39
+ args = Regexp.last_match(2)
40
+ [TYPE_VOIDP, func, args]
41
+ when /^([\w*\s]+[*\s])(\w+)\((.*?)\);?$/
42
+ ret = Regexp.last_match(1).strip
43
+ func = Regexp.last_match(2)
44
+ args = Regexp.last_match(3)
45
+ [ret, func, args]
46
+ else
47
+ raise("can't parse the function prototype: #{signature}")
48
+ end
49
+ end
50
+
51
+ def extern(signature, *opts)
52
+ symname, ctype, argtype, inner_funcs = parse_signature(signature, type_alias)
53
+ opt = parse_bind_options(opts)
54
+ f = import_function(symname, ctype, argtype, opt[:call_type])
55
+
56
+ f.inner_functions = inner_funcs # Added
57
+ f.argtype = argtype # Added
58
+
59
+ name = symname.gsub(/@.+/, '')
60
+ @func_map[name] = f
61
+ # define_method(name){|*args,&block| f.call(*args,&block)}
62
+ begin
63
+ /^(.+?):(\d+)/ =~ caller.first
64
+ file = Regexp.last_match(1)
65
+ line = Regexp.last_match(2).to_i
66
+ rescue StandardError
67
+ file, line = __FILE__, __LINE__ + 3
68
+ end
69
+ module_eval(<<-EOS, file, line)
70
+ def #{name}(*args, &block)
71
+ @func_map['#{name}'].call(*args,&block)
72
+ end
73
+ EOS
74
+ module_function(name)
75
+ f
76
+ end
77
+ end
78
+ end
79
+
5
80
  module LibUI
6
81
  module FFI
7
82
  extend Fiddle::Importer
@@ -13,20 +88,12 @@ module LibUI
13
88
  end
14
89
 
15
90
  class << self
16
- attr_reader :ffi_methods
91
+ attr_reader :func_map
17
92
 
18
- # Improved extern method.
19
- # 1. Ignore functions that cannot be attached.
20
- # 2. Available function (names) are stored in @ffi_methods.
21
93
  def try_extern(signature, *opts)
22
- @ffi_methods ||= []
23
- begin
24
- func = extern(signature, *opts)
25
- @ffi_methods << func.name
26
- func
27
- rescue StandardError => e
28
- warn "#{e.class.name}: #{e.message}"
29
- end
94
+ extern(signature, *opts)
95
+ rescue StandardError => e
96
+ warn "#{e.class.name}: #{e.message}"
30
97
  end
31
98
  end
32
99
 
@@ -401,6 +468,11 @@ module LibUI
401
468
 
402
469
  try_extern 'uiAttribute *uiNewUnderlineColorAttribute(uiUnderlineColor u, double r, double g, double b, double a)'
403
470
  try_extern 'void uiAttributeUnderlineColor(const uiAttribute *a, uiUnderlineColor *u, double *r, double *g, double *b, double *alpha)'
471
+
472
+ # uiOpenTypeFeatures
473
+
474
+ typealias 'uiOpenTypeFeaturesForEachFunc', 'void*'
475
+
404
476
  try_extern 'uiOpenTypeFeatures *uiNewOpenTypeFeatures(void)'
405
477
  try_extern 'void uiFreeOpenTypeFeatures(uiOpenTypeFeatures *otf)'
406
478
  try_extern 'uiOpenTypeFeatures *uiOpenTypeFeaturesClone(const uiOpenTypeFeatures *otf)'
@@ -410,6 +482,11 @@ module LibUI
410
482
  try_extern 'void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data)'
411
483
  try_extern 'uiAttribute *uiNewFeaturesAttribute(const uiOpenTypeFeatures *otf)'
412
484
  try_extern 'const uiOpenTypeFeatures *uiAttributeFeatures(const uiAttribute *a)'
485
+
486
+ # uiAttributedString
487
+
488
+ typealias 'uiAttributedStringForEachAttributeFunc', 'void*'
489
+
413
490
  try_extern 'uiAttributedString *uiNewAttributedString(const char *initialString)'
414
491
  try_extern 'void uiFreeAttributedString(uiAttributedString *s)'
415
492
  try_extern 'const char *uiAttributedStringString(const uiAttributedString *s)'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LibUI
4
- VERSION = '0.0.4.alpha'
4
+ VERSION = '0.0.5.alpha'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.alpha
4
+ version: 0.0.5.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - kojix2
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-09 00:00:00.000000000 Z
11
+ date: 2020-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler