freetype 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +8 -18
- data/lib/freetype/api.rb +31 -118
- data/lib/freetype/api_test.rb +53 -76
- data/lib/freetype/c.rb +3 -0
- data/lib/freetype/c_test.rb +47 -16
- data/lib/freetype/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c36f62b7c9de44960d5c1610bdad80291833313e
|
4
|
+
data.tar.gz: 46b17c2d49414d9fdad8b8ea6072b342286aab00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 372d0d55f362b88693b72d12e17336319afea3b75a2a67d1eaedaaa235c02e775f86652e71764a4f5644b3451c98a3e23bced0ff7f31e4819866546877c936a3
|
7
|
+
data.tar.gz: 55ac0bd04129157365706a0a91ffe5aceea88e3c5f4108ffd0563a40e0e589bb8dd972c33ba0167540228c4962e66ec184eefc88b949543a1add02bacc5285b8
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# FreeType
|
2
2
|
|
3
|
+
[](https://travis-ci.org/ksss/freetype)
|
4
|
+
|
3
5
|
FreeType is freetype wrapper using by ffi
|
4
6
|
|
5
7
|
## Installation
|
@@ -78,27 +80,15 @@ raise FreeType::Error.find(err) unless err == 0
|
|
78
80
|
|
79
81
|
```ruby
|
80
82
|
require 'freetype/api'
|
83
|
+
# or require 'freetype'
|
81
84
|
|
82
85
|
include FreeType::API
|
83
86
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
p face.kerning_unfitted('A', 'W') #=> #<FreeType::API::Vector x=-10 y=0>
|
90
|
-
end
|
91
|
-
end
|
92
|
-
```
|
93
|
-
|
94
|
-
### Use All
|
95
|
-
|
96
|
-
```ruby
|
97
|
-
require 'freetype'
|
98
|
-
|
99
|
-
FreeType::API::Library.open do |lib|
|
100
|
-
face = FFI::MemoryPointer.new(:pointer)
|
101
|
-
FreeType::C::FT_New_Face(lib.pointer, 'font.otf', 0, face)
|
87
|
+
Font.open('font.ttf') do |font|
|
88
|
+
font.set_char_size(0, 32 * 32, 300, 300)
|
89
|
+
outline = font.glyph('a').outline
|
90
|
+
p outline.points #=> [#<FreeType::API::Outline tag=-1 x= 10 y=24>, ...]
|
91
|
+
p font.kerning_unfitted('A', 'W') #=> #<FreeType::API::Vector x=-10 y=0>
|
102
92
|
end
|
103
93
|
```
|
104
94
|
|
data/lib/freetype/api.rb
CHANGED
@@ -4,6 +4,22 @@ require 'freetype/error'
|
|
4
4
|
module FreeType
|
5
5
|
# high level API for freetype wrapping by FFI
|
6
6
|
module API
|
7
|
+
def library_version
|
8
|
+
library = ::FFI::MemoryPointer.new(:pointer)
|
9
|
+
err = FreeType::C::FT_Init_FreeType(library)
|
10
|
+
raise FreeType::Error.find(err) unless err == 0
|
11
|
+
|
12
|
+
amajor = ::FFI::MemoryPointer.new(:int)
|
13
|
+
aminor = ::FFI::MemoryPointer.new(:int)
|
14
|
+
apatch = ::FFI::MemoryPointer.new(:int)
|
15
|
+
FreeType::C::FT_Library_Version(library.get_pointer(0), amajor, aminor, apatch)
|
16
|
+
"#{amajor.get_int(0)}.#{aminor.get_int(0)}.#{apatch.get_int(0)}"
|
17
|
+
ensure
|
18
|
+
err = FreeType::C::FT_Done_Library(library.get_pointer(0))
|
19
|
+
raise FreeType::Error.find(err) unless err == 0
|
20
|
+
end
|
21
|
+
module_function :library_version
|
22
|
+
|
7
23
|
module IOInterface
|
8
24
|
def open(*args)
|
9
25
|
i = new(*args)
|
@@ -19,58 +35,30 @@ module FreeType
|
|
19
35
|
end
|
20
36
|
end
|
21
37
|
|
22
|
-
class
|
38
|
+
class Font
|
23
39
|
extend IOInterface
|
24
40
|
include C
|
25
41
|
|
26
|
-
|
42
|
+
attr_reader :face
|
43
|
+
def initialize(font_path)
|
27
44
|
@library = ::FFI::MemoryPointer.new(:pointer)
|
28
45
|
err = FT_Init_FreeType(@library)
|
29
46
|
raise FreeType::Error.find(err) unless err == 0
|
30
|
-
end
|
31
|
-
|
32
|
-
def face_open(font)
|
33
|
-
Face.open(pointer, font) do |f|
|
34
|
-
yield f
|
35
|
-
end
|
36
|
-
end
|
37
47
|
|
38
|
-
|
39
|
-
@library.get_pointer(0)
|
40
|
-
end
|
48
|
+
@font_path = font_path
|
41
49
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
FT_Library_Version(@library.get_pointer(0), amajor, aminor, apatch)
|
47
|
-
"#{amajor.get_int(0)}.#{aminor.get_int(0)}.#{apatch.get_int(0)}"
|
50
|
+
f = ::FFI::MemoryPointer.new(:pointer)
|
51
|
+
err = FT_New_Face(@library.get_pointer(0), @font_path, 0, f)
|
52
|
+
raise FreeType::Error.find(err) unless err == 0
|
53
|
+
@face = FT_FaceRec.new(f.get_pointer(0))
|
48
54
|
end
|
49
55
|
|
50
56
|
def close
|
51
|
-
err =
|
57
|
+
err = FT_Done_Face(@face)
|
52
58
|
raise FreeType::Error.find(err) unless err == 0
|
53
|
-
@library.free
|
54
|
-
end
|
55
|
-
end
|
56
59
|
|
57
|
-
|
58
|
-
extend IOInterface
|
59
|
-
include C
|
60
|
-
|
61
|
-
attr_reader :font_path
|
62
|
-
def initialize(library, font_path)
|
63
|
-
@library = library
|
64
|
-
@font_path = font_path
|
65
|
-
@outline = nil
|
66
|
-
f = ::FFI::MemoryPointer.new(:pointer)
|
67
|
-
err = FT_New_Face(@library, @font_path, 0, f)
|
60
|
+
err = FT_Done_Library(@library.get_pointer(0))
|
68
61
|
raise FreeType::Error.find(err) unless err == 0
|
69
|
-
@face = FT_FaceRec.new(f.get_pointer(0))
|
70
|
-
end
|
71
|
-
|
72
|
-
def raw
|
73
|
-
@face
|
74
62
|
end
|
75
63
|
|
76
64
|
def select_charmap(enc_code)
|
@@ -122,11 +110,6 @@ module FreeType
|
|
122
110
|
get_kerning(before_char, after_char, :FT_KERNING_UNSCALED)
|
123
111
|
end
|
124
112
|
|
125
|
-
def close
|
126
|
-
err = FT_Done_Face(@face)
|
127
|
-
raise FreeType::Error.find(err) unless err == 0
|
128
|
-
end
|
129
|
-
|
130
113
|
private
|
131
114
|
|
132
115
|
def get_kerning(before_char, after_char, kerning_mode)
|
@@ -164,8 +147,8 @@ module FreeType
|
|
164
147
|
@glyph = glyph
|
165
148
|
end
|
166
149
|
|
167
|
-
def
|
168
|
-
@glyph
|
150
|
+
def [](key)
|
151
|
+
@glyph[key]
|
169
152
|
end
|
170
153
|
|
171
154
|
def metrics
|
@@ -176,7 +159,7 @@ module FreeType
|
|
176
159
|
Outline.new(@glyph[:outline])
|
177
160
|
end
|
178
161
|
|
179
|
-
def
|
162
|
+
def char_width
|
180
163
|
@glyph[:metrics][:horiAdvance]
|
181
164
|
end
|
182
165
|
end
|
@@ -188,8 +171,8 @@ module FreeType
|
|
188
171
|
@outline = outline
|
189
172
|
end
|
190
173
|
|
191
|
-
def
|
192
|
-
@outline
|
174
|
+
def [](key)
|
175
|
+
@outline[key]
|
193
176
|
end
|
194
177
|
|
195
178
|
def points
|
@@ -212,76 +195,6 @@ module FreeType
|
|
212
195
|
return [] if @outline[:n_points] == 0
|
213
196
|
@outline[:tags].get_array_of_char(0, @outline[:n_points])
|
214
197
|
end
|
215
|
-
|
216
|
-
def to_svg_path
|
217
|
-
end_ptd_of_counts = contours
|
218
|
-
contours = []
|
219
|
-
contour = []
|
220
|
-
points.each.with_index do |point, index|
|
221
|
-
contour << point
|
222
|
-
if index == end_ptd_of_counts.first
|
223
|
-
end_ptd_of_counts.shift
|
224
|
-
contours << contour
|
225
|
-
contour = []
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
path = []
|
230
|
-
contours.each do |contour|
|
231
|
-
first_pt = contour.first
|
232
|
-
last_pt = contour.last
|
233
|
-
curve_pt = nil
|
234
|
-
start = 0
|
235
|
-
if first_pt.on_curve?
|
236
|
-
curve_pt = nil
|
237
|
-
start = 1
|
238
|
-
else
|
239
|
-
if last_pt.on_curve?
|
240
|
-
first_pt = last_pt
|
241
|
-
else
|
242
|
-
first_pt = Point.new(0, (first_pt.x + last_pt.x) / 2, (first_pt.y + last_pt.y) / 2)
|
243
|
-
end
|
244
|
-
curve_pt = first_pt
|
245
|
-
end
|
246
|
-
path << ['M', first_pt.x, -first_pt.y]
|
247
|
-
|
248
|
-
prev_pt = nil
|
249
|
-
(start...contour.length).each do |j|
|
250
|
-
pt = contour[j]
|
251
|
-
prev_pt = if j == 0
|
252
|
-
first_pt
|
253
|
-
else
|
254
|
-
contour[j - 1]
|
255
|
-
end
|
256
|
-
|
257
|
-
if prev_pt.on_curve? && pt.on_curve?
|
258
|
-
path << ['L', pt.x, -pt.y]
|
259
|
-
elsif prev_pt.on_curve? && !pt.on_curve?
|
260
|
-
curve_pt = pt
|
261
|
-
elsif !prev_pt.on_curve? && !pt.on_curve?
|
262
|
-
path << ['Q', prev_pt.x, -prev_pt.y, (prev_pt.x + pt.x) / 2, -((prev_pt.y + pt.y) / 2)]
|
263
|
-
curve_pt = pt
|
264
|
-
elsif !prev_pt.on_curve? && pt.on_curve?
|
265
|
-
path << ['Q', curve_pt.x, -curve_pt.y, pt.x, -pt.y]
|
266
|
-
curve_pt = nil
|
267
|
-
else
|
268
|
-
raise
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
next unless first_pt != last_pt
|
273
|
-
if curve_pt
|
274
|
-
path << ['Q', curve_pt.x, -curve_pt.y, first_pt.x, -first_pt.y]
|
275
|
-
else
|
276
|
-
path << ['L', first_pt.x, -first_pt.y]
|
277
|
-
end
|
278
|
-
end
|
279
|
-
path << ['z'] if 0 < path.length
|
280
|
-
|
281
|
-
path.map { |(command, *args)|
|
282
|
-
"#{command}#{args.join(' ')}"
|
283
|
-
}.join('')
|
284
|
-
end
|
285
198
|
end
|
286
199
|
|
287
200
|
Point = Struct.new(:tag, :x, :y) do
|
data/lib/freetype/api_test.rb
CHANGED
@@ -3,98 +3,74 @@ require 'freetype/api'
|
|
3
3
|
module FreeTypeApiTest
|
4
4
|
include FreeType::API
|
5
5
|
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
f.set_char_size(0, 0, 300, 300)
|
11
|
-
yield f
|
12
|
-
end
|
6
|
+
def font_open
|
7
|
+
['data/Prida01.otf', 'data/Starjedi.ttf'].each do |font|
|
8
|
+
Font.open(font) do |f|
|
9
|
+
yield f, font
|
13
10
|
end
|
14
11
|
end
|
15
12
|
end
|
16
13
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def test_library_version(t)
|
15
|
+
v = FreeType::API.library_version
|
16
|
+
unless String === v
|
17
|
+
t.error 'return value was break'
|
18
|
+
end
|
19
|
+
unless /\A\d+.\d+.\d+\z/ =~ v
|
20
|
+
t.error "version format was break got #{v}"
|
21
|
+
end
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def test_Font(t)
|
25
|
+
font = nil
|
26
|
+
ret = Font.open('data/Prida01.otf') do |f|
|
27
|
+
font = f
|
25
28
|
|
26
29
|
:abc
|
27
30
|
end
|
28
|
-
if
|
31
|
+
if font.nil?
|
29
32
|
t.error('cannot get FT_Library in `open` with block')
|
30
33
|
end
|
31
34
|
if ret != :abc
|
32
35
|
t.error 'want to return last value in block'
|
33
36
|
end
|
34
|
-
end
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
t.error('recommend warn miss?')
|
66
|
-
end
|
67
|
-
else
|
68
|
-
t.error('check freetype spec')
|
69
|
-
ensure
|
70
|
-
$stderr = origerr
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
f.set_char_size(0, 0, 300, 300)
|
75
|
-
|
76
|
-
bbox = f.bbox
|
77
|
-
unless BBox === bbox
|
78
|
-
t.error('FreeType::API::Face#bbox return value was break')
|
79
|
-
end
|
80
|
-
|
81
|
-
unless Glyph === f.glyph('a')
|
82
|
-
t.error 'return value was break'
|
83
|
-
end
|
84
|
-
|
85
|
-
# unless Glyph === f.notdef
|
86
|
-
# t.error 'return value was break'
|
87
|
-
# end
|
88
|
-
end
|
38
|
+
font_open do |f, _font|
|
39
|
+
if f.char_index('a') == 0
|
40
|
+
t.error('ascii char not defined this font')
|
41
|
+
end
|
42
|
+
if f.char_index('㍿') != 0
|
43
|
+
t.error("I don't know why set character was defined in font")
|
44
|
+
end
|
45
|
+
|
46
|
+
v = f.kerning('A', 'W')
|
47
|
+
unless v
|
48
|
+
t.error('#kerning return object was changed')
|
49
|
+
end
|
50
|
+
unless Fixnum === v.x && Fixnum === v.y
|
51
|
+
t.error('Not vector object. Check spec for FT_Get_Kerning()')
|
52
|
+
end
|
53
|
+
|
54
|
+
f.set_char_size(0, 0, 300, 300)
|
55
|
+
|
56
|
+
bbox = f.bbox
|
57
|
+
unless BBox === bbox
|
58
|
+
t.error('FreeType::API::Face#bbox return value was break')
|
59
|
+
end
|
60
|
+
|
61
|
+
unless Glyph === f.glyph('a')
|
62
|
+
t.error 'return value was break'
|
63
|
+
end
|
64
|
+
|
65
|
+
unless Glyph === f.notdef
|
66
|
+
t.error 'return value was break'
|
89
67
|
end
|
90
|
-
end
|
91
|
-
if face.nil?
|
92
|
-
t.error('cannot get FT_Face in `open` with block')
|
93
68
|
end
|
94
69
|
end
|
95
70
|
|
96
71
|
def test_glyph(t)
|
97
|
-
|
72
|
+
font_open do |f|
|
73
|
+
f.set_char_size(0, 0, 300, 300)
|
98
74
|
table = { 'a' => nil, 'b' => nil, 'c' => nil, 'd' => nil }
|
99
75
|
table.each do |char, _|
|
100
76
|
glyph = f.glyph(char)
|
@@ -104,8 +80,8 @@ module FreeTypeApiTest
|
|
104
80
|
t.error 'return value was break'
|
105
81
|
end
|
106
82
|
|
107
|
-
|
108
|
-
unless Fixnum ===
|
83
|
+
char_width = glyph.char_width
|
84
|
+
unless Fixnum === char_width
|
109
85
|
t.error 'return value was break'
|
110
86
|
end
|
111
87
|
|
@@ -118,7 +94,8 @@ module FreeTypeApiTest
|
|
118
94
|
end
|
119
95
|
|
120
96
|
def test_outline(t)
|
121
|
-
|
97
|
+
font_open do |f|
|
98
|
+
f.set_char_size(0, 0, 300, 300)
|
122
99
|
table = { 'a' => nil, 'b' => nil, 'c' => nil, 'd' => nil }
|
123
100
|
table.each do |char, _|
|
124
101
|
outline = f.glyph(char).outline
|
data/lib/freetype/c.rb
CHANGED
@@ -235,6 +235,9 @@ module FreeType
|
|
235
235
|
# id = FT_Get_Char_Index(face, 'A'.ord) -> glyph id or 0 (undefined)
|
236
236
|
attach_function :FT_Get_Char_Index, [:pointer, :ulong], :uint
|
237
237
|
|
238
|
+
# err = FT_Get_Glyph_Name(face, 0, buff, 32)
|
239
|
+
attach_function :FT_Get_Glyph_Name, [:pointer, :uint, :pointer, :uint], :FT_Error
|
240
|
+
|
238
241
|
# v = FT_Vector.new
|
239
242
|
# err = FT_Get_Kerning(face, before_id, id, :FT_KERNING_DEFAULT, v)
|
240
243
|
# p v
|
data/lib/freetype/c_test.rb
CHANGED
@@ -12,11 +12,19 @@ module FFITest
|
|
12
12
|
|
13
13
|
FONTS.each do |font|
|
14
14
|
face = ::FFI::MemoryPointer.new(:pointer)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
begin
|
16
|
+
err = FT_New_Face(library.get_pointer(0), font, 0, face)
|
17
|
+
raise FreeType::Error.find(err) unless err == 0
|
18
|
+
|
19
|
+
yield FT_FaceRec.new(face.get_pointer(0)), font
|
20
|
+
ensure
|
21
|
+
err = FT_Done_Face(face.get_pointer(0))
|
22
|
+
raise FreeType::Error.find(err) unless err == 0
|
23
|
+
end
|
19
24
|
end
|
25
|
+
ensure
|
26
|
+
err = FT_Done_Library(library.get_pointer(0))
|
27
|
+
raise FreeType::Error.find(err) unless err == 0
|
20
28
|
end
|
21
29
|
|
22
30
|
def test_Library(t)
|
@@ -38,6 +46,12 @@ module FFITest
|
|
38
46
|
unless a.all? { |i| Fixnum === i }
|
39
47
|
t.error 'miss get values from FT_Library_Version()'
|
40
48
|
end
|
49
|
+
t.log "freetype version: #{a.join('.')}"
|
50
|
+
ensure
|
51
|
+
err = FT_Done_Library(library.get_pointer(0))
|
52
|
+
if err != 0
|
53
|
+
t.error FreeType::Error.find(err).message
|
54
|
+
end
|
41
55
|
end
|
42
56
|
|
43
57
|
def test_Face(t)
|
@@ -53,24 +67,28 @@ module FFITest
|
|
53
67
|
t.fatal FreeType::Error.find(err).message
|
54
68
|
end
|
55
69
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
70
|
+
begin
|
71
|
+
face = FT_FaceRec.new(face.get_pointer(0))
|
72
|
+
err = FT_Select_Charmap(face, :FT_ENCODING_UNICODE)
|
73
|
+
if err != 0
|
74
|
+
t.error FreeType::Error.find(err).message
|
75
|
+
end
|
76
|
+
ensure
|
77
|
+
err = FT_Done_Face(face)
|
78
|
+
if err != 0
|
79
|
+
t.error FreeType::Error.find(err).message
|
80
|
+
end
|
60
81
|
end
|
61
82
|
end
|
83
|
+
ensure
|
84
|
+
err = FT_Done_Library(library.get_pointer(0))
|
85
|
+
if err != 0
|
86
|
+
t.error FreeType::Error.find(err).message
|
87
|
+
end
|
62
88
|
end
|
63
89
|
|
64
90
|
def test_FT_Set_Char_Size(t)
|
65
91
|
libopen do |face|
|
66
|
-
if /darwin/ =~ RUBY_PLATFORM
|
67
|
-
err = FT_Load_Char(face, 'a'.ord, FreeType::C::FT_LOAD_DEFAULT)
|
68
|
-
e = FreeType::Error.find(err)
|
69
|
-
unless FreeType::Error::Invalid_Size_Handle === e
|
70
|
-
t.fatal 'check freetype spec'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
92
|
err = FT_Set_Char_Size(face, 0, 32, 300, 300)
|
75
93
|
if err != 0
|
76
94
|
t.error FreeType::Error.find(err).message
|
@@ -83,6 +101,19 @@ module FFITest
|
|
83
101
|
end
|
84
102
|
end
|
85
103
|
|
104
|
+
def test_FT_Get_Glyph_Name(t)
|
105
|
+
libopen do |face|
|
106
|
+
buff = FFI::MemoryPointer.new(:pointer)
|
107
|
+
err = FT_Get_Glyph_Name(face, 0, buff, 32)
|
108
|
+
if err != 0
|
109
|
+
t.error FreeType::Error.find(err).message
|
110
|
+
end
|
111
|
+
unless String === buff.get_string(0)
|
112
|
+
t.error 'May buffering miss?'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
86
117
|
def test_char(t)
|
87
118
|
libopen do |face, _font|
|
88
119
|
err = FT_Set_Char_Size(face, 0, 32, 300, 300)
|
data/lib/freetype/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freetype
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ksss
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|