harfbuzz 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 88bd6dee65ceba054a1ff2ba5b4329bfea310689
4
+ data.tar.gz: fc6e012e4e25a3f579cea5946f9e6a7afcd963e4
5
+ SHA512:
6
+ metadata.gz: 4ddabd5869af1957fbe68864b1bba1f0dba915b0392f6c66549645b5d3f34ae1c6c2bffd473d104443cdd383aabcfc763dba1a1b2ffd0c2ebe28fa19fc058b7c
7
+ data.tar.gz: 1d5ed18e405ae2c595d31403898facdc1722f28d268176799042cfb8f9aeb18b505bbf2dfb6eac83f0e86225472cdec2613199660dde863f1e4cb3c7d3014f9f
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in itinerary.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 John Labovitz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ The Harfbuzz gem is a Ruby interface to the Harfbuzz text shaping engine. By using this gem, some input text, a font file, and a list of features, you can convert Unicode text to glyph descriptions that are ready to be rendered.
2
+
3
+ For more information about Harfbuzz itself, see [harfbuzz.org](http://harfbuzz.org).
4
+
5
+ For an example of use, see [example.rb](harfbuzz/examples/example.rb). From the base directory of this gem, you can run this example:
6
+
7
+ ruby examples/example.rb
8
+
9
+
10
+ ## Installation
11
+
12
+ You must have the Harfbuzz library available on your system. OS X users can use Homebrew to install it:
13
+
14
+ brew install harfbuzz
15
+
16
+ Once you've installed the Harfbuzz library, install this gem by the usual:
17
+
18
+ sudo gem install harfbuzz
19
+
20
+ or if you're using a Ruby installed in Homebrew, as a normal user:
21
+
22
+ gem install harfbuzz
23
+
24
+
25
+ ## Design philosophy
26
+
27
+ The Harfbuzz gem is composed of two layers: a low-level direct interface to Harfbuzz itself, and a high-level abstract interface that uses traditional Ruby objects and idioms.
28
+
29
+ The low-level interface is a one-to-one mapping of Harfbuzz C functions to Ruby methods, implemented using the [FFI](https://github.com/ffi/ffi) library. For example, the Harfbuzz C function `hb_version_string()` is available in Ruby as `Harfbuzz.hb_version_string`. However, as the low-level methods return C pointers wrapped in FFI objects, this layer is generally not useful to a Ruby programmer.
30
+
31
+ The high-level interface abstracts the C functions, structures, and pointers into Ruby objects. For example, the aftermentioned `hb_version_string()` function is more usefully available via `Harfbuzz.version_string`, which returns a Ruby string containing with the version of the Harfbuzz library.
32
+
33
+ Where appropriate, Ruby classes have been constructed to map to the concepts in Harfbuzz. Hence:
34
+
35
+ | C | Ruby
36
+ | ----------- | ----
37
+ | hb_blob_t | Harfbuzz::Blob
38
+ | hb_buffer_t | Harfbuzz::Buffer
39
+ | hb_face_t | Harfbuzz::Face
40
+ | hb_font_t | Harfbuzz::Font
41
+
42
+ The shaping method itself is in the base Harfbuzz module, as `Harfbuzz.shape(...)`.
43
+
44
+
45
+ ## Caveats & bugs
46
+
47
+ Only a small number of basic Harfbuzz functions are mapped to Ruby methods. More will be added as needed.
48
+
49
+ There is no documentation except this file and the example script.
50
+
51
+ There are no tests or specs.
52
+
53
+ Memory management may not be correct.
54
+
55
+
56
+ ## Feedback
57
+
58
+ As this is a new project, I'd love to hear your feedback. Email me at [johnl@johnlabovitz.com](mailto:johnl@johnlabovitz.com).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+ require 'bundler/gem_tasks'
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift 'lib'
4
+ require 'harfbuzz'
5
+
6
+ #
7
+ # Show some information about Harfbuzz
8
+ #
9
+
10
+ puts "Harfbuzz version: #{Harfbuzz.version_string}"
11
+ puts "Shapers: #{Harfbuzz.shapers.join(', ')}"
12
+
13
+ #
14
+ # Create a font to be used for shaping. To get the most of out this example, use an OpenType font.
15
+ #
16
+
17
+ face = Harfbuzz::Face.new(File.open('/Library/Fonts/ACaslonPro-Regular.otf', 'rb'))
18
+ font = Harfbuzz::Font.new(face)
19
+
20
+ #
21
+ # Create a buffer to hold the text and the resulting glyphs/positions.
22
+ #
23
+
24
+ buffer = Harfbuzz::Buffer.new
25
+
26
+ #
27
+ # Add some text to the buffer.
28
+ #
29
+
30
+ buffer.add_utf8('WAVE first.')
31
+
32
+ #
33
+ # Guess direction, script, & language from the text.
34
+ #
35
+
36
+ if true
37
+ buffer.guess_segment_properties
38
+ else
39
+ #FIXME: these functions are not yet bound
40
+ # hb_buffer_set_direction(buffer, hb_direction_from_string(direction, -1))
41
+ # hb_buffer_set_script(buffer, hb_script_from_string(script, -1))
42
+ # hb_buffer_set_language(buffer, hb_language_from_string(language, -1))
43
+ # hb_buffer_set_flags(buffer, shape_flags)
44
+ end
45
+
46
+ #
47
+ # Shape the text in the buffer using some interesting features.
48
+ #
49
+
50
+ Harfbuzz.shape(font, buffer, %w{+dlig +hlig})
51
+
52
+ #
53
+ # Normalize glyph clusters (FIXME: why?).
54
+ #
55
+
56
+ buffer.normalize_glyphs
57
+
58
+ #
59
+ # Iterate through the buffer, examining the glyphs & related positions.
60
+ #
61
+
62
+ glyph_infos = buffer.get_glyph_infos
63
+ glyph_positions = buffer.get_glyph_positions
64
+ buffer.length.times do |i|
65
+ info, position = glyph_infos[i], glyph_positions[i]
66
+ glyph_name = font.glyph_to_string(info[:codepoint])
67
+ puts "/%-10.10s %5u | mask: %04X | cluster: %2u | advance: %4u,%4u | offset: %4u,%4u" % [
68
+ glyph_name,
69
+ info[:codepoint],
70
+ info[:mask],
71
+ info[:cluster],
72
+ position[:x_advance], position[:y_advance],
73
+ position[:x_offset], position[:y_offset],
74
+ ]
75
+ end
data/harfbuzz.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ #encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'harfbuzz/version'
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = 'harfbuzz'
10
+ s.version = Harfbuzz::VERSION
11
+ s.summary = 'Ruby interface to the Harfbuzz text shaping engine'
12
+ s.author = 'John Labovitz'
13
+ s.email = 'johnl@johnlabovitz.com'
14
+ s.description = %q{
15
+ Harfbuzz is a Ruby interface to the Harfbuzz text shaping engine.
16
+ }
17
+ s.homepage = 'http://github.com/jslabovitz/harfbuzz-gem'
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_path = 'lib'
22
+
23
+ s.add_dependency 'ffi'
24
+
25
+ s.add_development_dependency 'bundler'
26
+ s.add_development_dependency 'rake'
27
+ end
data/lib/harfbuzz.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'ffi'
2
+
3
+ require 'harfbuzz/ffi_additions'
4
+
5
+ module Harfbuzz
6
+
7
+ extend FFI::Library
8
+
9
+ ffi_lib 'harfbuzz'
10
+
11
+ typedef :pointer, :hb_destroy_func_t
12
+ typedef :uint32, :hb_codepoint_t
13
+
14
+ attach_function :hb_version_string, [], :string
15
+ attach_function :hb_version, [:pointer, :pointer, :pointer], :void
16
+
17
+ def self.version_string
18
+ hb_version_string
19
+ end
20
+
21
+ def self.version
22
+ major_ptr = FFI::MemoryPointer.new(:uint, 1)
23
+ minor_ptr = FFI::MemoryPointer.new(:uint, 1)
24
+ micro_ptr = FFI::MemoryPointer.new(:uint, 1)
25
+ hb_version(major_ptr, minor_ptr, micro_ptr)
26
+ [
27
+ major_ptr.read_uint,
28
+ minor_ptr.read_uint,
29
+ micro_ptr.read_uint,
30
+ ]
31
+ end
32
+
33
+ end
34
+
35
+ require 'harfbuzz/base'
36
+ require 'harfbuzz/blob'
37
+ require 'harfbuzz/face'
38
+ require 'harfbuzz/font'
39
+ require 'harfbuzz/buffer'
40
+ require 'harfbuzz/shaping'
@@ -0,0 +1,17 @@
1
+ module Harfbuzz
2
+
3
+ class Base
4
+
5
+ def self.finalize(method, ptr)
6
+ proc {
7
+ Harfbuzz.send(method, ptr) unless ptr == 0
8
+ }
9
+ end
10
+
11
+ def define_finalizer(method, ptr)
12
+ ObjectSpace.define_finalizer(self, self.class.finalize(method, ptr))
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,41 @@
1
+ module Harfbuzz
2
+
3
+ typedef :pointer, :hb_blob_t
4
+
5
+ enum :hb_memory_mode_t, [
6
+ :HB_MEMORY_MODE_DUPLICATE,
7
+ :HB_MEMORY_MODE_READONLY,
8
+ :HB_MEMORY_MODE_WRITABLE,
9
+ :HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
10
+ ]
11
+
12
+ attach_function :hb_blob_create, [
13
+ :pointer, # data
14
+ :uint, # length
15
+ :hb_memory_mode_t, # mode,
16
+ :pointer, # user_data,
17
+ :hb_destroy_func_t, # destroy
18
+ ], :hb_blob_t
19
+ attach_function :hb_blob_get_length, [
20
+ :hb_blob_t, # blob
21
+ ], :uint
22
+ attach_function :hb_blob_destroy, [:hb_blob_t], :void
23
+
24
+ class Blob < Base
25
+
26
+ attr_reader :hb_blob
27
+
28
+ def initialize(data, mode=0, user_data=nil)
29
+ data_ptr = FFI::MemoryPointer.new(:char, data.size)
30
+ data_ptr.put_bytes(0, data)
31
+ @hb_blob = Harfbuzz.hb_blob_create(data_ptr, data.size, mode, user_data, nil)
32
+ define_finalizer(:hb_blob_destroy, @hb_blob)
33
+ end
34
+
35
+ def length
36
+ Harfbuzz.hb_blob_get_length(@hb_blob)
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,103 @@
1
+ module Harfbuzz
2
+
3
+ typedef :pointer, :hb_buffer_t
4
+ typedef :uint32, :hb_mask_t
5
+ typedef :int32, :hb_position_t
6
+
7
+ class GlyphInfo < FFI::Struct
8
+
9
+ layout \
10
+ :codepoint, :hb_codepoint_t,
11
+ :mask, :hb_mask_t,
12
+ :cluster, :uint32,
13
+ :var1, :uint32, # private
14
+ :var2, :uint32 # private
15
+
16
+ end
17
+
18
+ class GlyphPosition < FFI::Struct
19
+
20
+ layout \
21
+ :x_advance, :hb_position_t,
22
+ :y_advance, :hb_position_t,
23
+ :x_offset, :hb_position_t,
24
+ :y_offset, :hb_position_t,
25
+ :var, :uint32 # private
26
+
27
+ def inspect
28
+ "<#{self} %s>" % [
29
+ %w{x_advance y_advance x_offset y_offset}.map { |k|
30
+ "#{k} = #{self[k.to_sym].inspect}"
31
+ }.join(', ')
32
+ ]
33
+ end
34
+
35
+ end
36
+
37
+ attach_function :hb_buffer_create, [], :hb_buffer_t
38
+ attach_function :hb_buffer_add_utf8, [
39
+ :hb_buffer_t, # buffer
40
+ :pointer, # text
41
+ :int, # text_length
42
+ :uint, # item_offset
43
+ :int, # item_length
44
+ ], :void
45
+ attach_function :hb_buffer_guess_segment_properties, [:hb_buffer_t], :void
46
+ attach_function :hb_buffer_get_length, [:hb_buffer_t], :uint
47
+ attach_function :hb_buffer_get_glyph_infos, [
48
+ :hb_buffer_t, # buffer
49
+ :pointer, # length
50
+ ], GlyphInfo
51
+ attach_function :hb_buffer_get_glyph_positions, [
52
+ :hb_buffer_t, # buffer
53
+ :pointer, # length
54
+ ], GlyphPosition
55
+ attach_function :hb_buffer_normalize_glyphs, [:hb_buffer_t], :void
56
+
57
+ class Buffer < Base
58
+
59
+ attr_reader :hb_buffer
60
+
61
+ def initialize
62
+ @hb_buffer = Harfbuzz.hb_buffer_create
63
+ define_finalizer(:hb_buffer_destroy, @hb_buffer)
64
+ end
65
+
66
+ def add_utf8(text, offset=0, length=-1)
67
+ text_ptr = FFI::MemoryPointer.new(:char, text.bytesize)
68
+ text_ptr.put_bytes(0, text)
69
+ Harfbuzz.hb_buffer_add_utf8(@hb_buffer, text_ptr, text.bytesize, offset, length)
70
+ end
71
+
72
+ def guess_segment_properties
73
+ Harfbuzz.hb_buffer_guess_segment_properties(@hb_buffer)
74
+ end
75
+
76
+ def normalize_glyphs
77
+ Harfbuzz.hb_buffer_normalize_glyphs(@hb_buffer)
78
+ end
79
+
80
+ def length
81
+ Harfbuzz.hb_buffer_get_length(@hb_buffer)
82
+ end
83
+
84
+ def get_glyph_infos
85
+ length_ptr = FFI::MemoryPointer.new(:uint, 1)
86
+ info_ptr = Harfbuzz.hb_buffer_get_glyph_infos(@hb_buffer, length_ptr)
87
+ length = length_ptr.read_uint
88
+ length.times.map do |i|
89
+ GlyphInfo.new(info_ptr + (i * GlyphInfo.size))
90
+ end
91
+ end
92
+
93
+ def get_glyph_positions
94
+ length_ptr = FFI::MemoryPointer.new(:uint, 1)
95
+ positions_ptr = Harfbuzz.hb_buffer_get_glyph_positions(@hb_buffer, length_ptr)
96
+ length = length_ptr.read_uint
97
+ length.times.map do |i|
98
+ GlyphPosition.new(positions_ptr + (i * GlyphPosition.size))
99
+ end
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,46 @@
1
+ module Harfbuzz
2
+
3
+ typedef :pointer, :hb_face_t
4
+
5
+ attach_function :hb_face_create, [
6
+ :hb_blob_t, # blob
7
+ :uint, # index
8
+ ], :hb_face_t
9
+ attach_function :hb_face_get_index, [:hb_face_t], :uint
10
+ attach_function :hb_face_get_upem, [:hb_face_t], :uint
11
+ attach_function :hb_face_get_glyph_count, [:hb_face_t], :uint
12
+
13
+ class Face < Base
14
+
15
+ attr_reader :hb_face
16
+
17
+ def initialize(input, face_index=0)
18
+ blob = case input
19
+ when IO
20
+ Harfbuzz::Blob.new(input.read, :HB_MEMORY_MODE_READONLY)
21
+ when Blob
22
+ # use as-is
23
+ when String
24
+ Harfbuzz::Blob.new(input, :HB_MEMORY_MODE_READONLY)
25
+ else
26
+ raise "Unknown input type: #{input.class}"
27
+ end
28
+ @hb_face = Harfbuzz.hb_face_create(blob.hb_blob, face_index)
29
+ define_finalizer(:hb_buffer_destroy, @hb_face)
30
+ end
31
+
32
+ def index
33
+ Harfbuzz.hb_face_get_index(@hb_face)
34
+ end
35
+
36
+ def upem
37
+ Harfbuzz.hb_face_get_upem(@hb_face)
38
+ end
39
+
40
+ def glyph_count
41
+ Harfbuzz.hb_face_get_glyph_count(@hb_face)
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,30 @@
1
+ class FFI::Pointer
2
+
3
+ # after https://dzone.com/articles/getting-array-strings-char-ffi
4
+
5
+ def read_array_of_strings
6
+ elements = []
7
+ loc = self
8
+ until (element = loc.read_pointer).null?
9
+ elements << element.read_string
10
+ loc += FFI::Type::POINTER.size
11
+ end
12
+ elements
13
+ end
14
+
15
+ end
16
+
17
+ class FFI::MemoryPointer
18
+
19
+ # after http://zegoggl.es/2009/05/ruby-ffi-recipes.html
20
+
21
+ def self.from_array_of_strings(strings)
22
+ string_ptrs = strings.map { |s| FFI::MemoryPointer.from_string(s) } + [nil]
23
+ strings_ptr = new(:pointer, string_ptrs.length)
24
+ string_ptrs.each_with_index do |ptr, i|
25
+ strings_ptr[i].put_pointer(0, ptr)
26
+ end
27
+ strings_ptr
28
+ end
29
+
30
+ end
@@ -0,0 +1,68 @@
1
+ module Harfbuzz
2
+
3
+ typedef :pointer, :hb_font_t
4
+
5
+ attach_function :hb_font_create, [:hb_face_t], :hb_font_t
6
+ attach_function :hb_font_set_scale, [
7
+ :hb_font_t, # font
8
+ :int, # x_scale
9
+ :int, # y_scale
10
+ ], :void
11
+ attach_function :hb_ft_font_set_funcs, [:hb_font_t], :void
12
+ attach_function :hb_font_get_scale, [
13
+ :hb_font_t, # font
14
+ :pointer, # int *x_scale
15
+ :pointer, # int *y_scale
16
+ ], :void
17
+ attach_function :hb_font_get_ppem, [
18
+ :hb_font_t, # font
19
+ :pointer, # unsigned int *x_ppem
20
+ :pointer, # unsigned int *y_ppem
21
+ ], :void
22
+ attach_function :hb_font_glyph_to_string, [
23
+ :hb_font_t, # font
24
+ :hb_codepoint_t, # glyph
25
+ :pointer, # s
26
+ :uint, # size
27
+ ], :void
28
+
29
+ class Font < Base
30
+
31
+ attr_reader :hb_font
32
+
33
+ def initialize(face)
34
+ @hb_font = Harfbuzz.hb_font_create(face.hb_face)
35
+ Harfbuzz.hb_font_set_scale(@hb_font, face.upem, face.upem)
36
+ Harfbuzz.hb_ft_font_set_funcs(@hb_font)
37
+ define_finalizer(:hb_font_destroy, @hb_font)
38
+ end
39
+
40
+ def scale
41
+ x_scale_ptr = FFI::MemoryPointer.new(:int, 1)
42
+ y_scale_ptr = FFI::MemoryPointer.new(:int, 1)
43
+ Harfbuzz.hb_font_get_scale(@hb_font, x_scale_ptr, y_scale_ptr)
44
+ [
45
+ x_scale_ptr.read_int,
46
+ y_scale_ptr.read_int,
47
+ ]
48
+ end
49
+
50
+ def ppem
51
+ ppem_x_ptr = FFI::MemoryPointer.new(:uint, 1)
52
+ ppem_y_ptr = FFI::MemoryPointer.new(:uint, 1)
53
+ Harfbuzz.hb_font_get_ppem(@hb_font, ppem_x_ptr, ppem_y_ptr)
54
+ [
55
+ ppem_x_ptr.read_uint,
56
+ ppem_y_ptr.read_uint,
57
+ ]
58
+ end
59
+
60
+ def glyph_to_string(glyph)
61
+ string_ptr = FFI::MemoryPointer.new(:char, 20)
62
+ Harfbuzz.hb_font_glyph_to_string(@hb_font, glyph, string_ptr, 20)
63
+ string_ptr.get_string(0, 20)
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,75 @@
1
+ module Harfbuzz
2
+
3
+ typedef :uint32, :hb_tag_t
4
+
5
+ class Feature < FFI::Struct
6
+
7
+ layout \
8
+ :tag, :hb_tag_t,
9
+ :value, :uint32,
10
+ :start, :uint,
11
+ :end, :uint
12
+
13
+ end
14
+
15
+ # typedef Feature, :hb_feature_t
16
+
17
+ attach_function :hb_shape_list_shapers, [], :pointer
18
+ attach_function :hb_shape, [
19
+ :hb_font_t, # font
20
+ :hb_buffer_t, # buffer
21
+ :pointer, # features
22
+ :uint, # num_features
23
+ ], :void
24
+ attach_function :hb_shape_full, [
25
+ :hb_font_t, # font
26
+ :hb_buffer_t, # buffer
27
+ :pointer, # features
28
+ :uint, # num_features
29
+ :pointer, # shaper_list
30
+ ], :bool
31
+ attach_function :hb_feature_from_string, [
32
+ :pointer, # str
33
+ :int, # len
34
+ Feature.by_ref, # feature
35
+ ], :bool
36
+ attach_function :hb_feature_to_string, [
37
+ Feature.by_ref, # feature
38
+ :pointer, # buf
39
+ :uint, # size,
40
+ ], :void
41
+
42
+ def self.shapers
43
+ Harfbuzz.hb_shape_list_shapers.read_array_of_strings
44
+ end
45
+
46
+ def self.shape(font, buffer, features=nil, shapers=nil)
47
+ features_ptr, features_len = features_from_strings(features)
48
+ shapers_ptr = shapers ? FFI::MemoryPointer.from_array_of_strings(shapers) : nil
49
+ Harfbuzz.hb_shape_full(
50
+ font.hb_font,
51
+ buffer.hb_buffer,
52
+ features_ptr,
53
+ features_len,
54
+ shapers_ptr,
55
+ )
56
+ end
57
+
58
+ def self.features_from_strings(feature_strings)
59
+ features_len = feature_strings ? feature_strings.length : 0
60
+ if features_len > 0
61
+ features_ptr = FFI::MemoryPointer.new(Feature, features_len)
62
+ feature_strings.each_with_index do |feature_string, i|
63
+ feature_string_ptr = FFI::MemoryPointer.new(:char, feature_string.bytesize)
64
+ feature_string_ptr.put_bytes(0, feature_string)
65
+ feature_ptr = Feature.new(features_ptr + (i * Feature.size))
66
+ hb_feature_from_string(feature_string_ptr, feature_string.bytesize, feature_ptr) \
67
+ or raise "Can't get feature from string: #{feature_string.inspect}"
68
+ end
69
+ else
70
+ features_ptr = nil
71
+ end
72
+ [features_ptr, features_len]
73
+ end
74
+
75
+ end
@@ -0,0 +1,5 @@
1
+ module Harfbuzz
2
+
3
+ VERSION = '0.1'
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: harfbuzz
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - John Labovitz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: "\n Harfbuzz is a Ruby interface to the Harfbuzz text shaping engine.\n
56
+ \ "
57
+ email: johnl@johnlabovitz.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - examples/example.rb
68
+ - harfbuzz.gemspec
69
+ - lib/harfbuzz.rb
70
+ - lib/harfbuzz/base.rb
71
+ - lib/harfbuzz/blob.rb
72
+ - lib/harfbuzz/buffer.rb
73
+ - lib/harfbuzz/face.rb
74
+ - lib/harfbuzz/ffi_additions.rb
75
+ - lib/harfbuzz/font.rb
76
+ - lib/harfbuzz/shaping.rb
77
+ - lib/harfbuzz/version.rb
78
+ homepage: http://github.com/jslabovitz/harfbuzz-gem
79
+ licenses: []
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.4.8
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Ruby interface to the Harfbuzz text shaping engine
101
+ test_files: []