freetype 0.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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +9 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +121 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/data/Prida01.otf +0 -0
- data/data/Starjedi.ttf +0 -0
- data/freetype.gemspec +26 -0
- data/lib/freetype.rb +5 -0
- data/lib/freetype/api.rb +296 -0
- data/lib/freetype/api_test.rb +149 -0
- data/lib/freetype/c.rb +243 -0
- data/lib/freetype/c_test.rb +173 -0
- data/lib/freetype/error.rb +118 -0
- data/lib/freetype/error_test.rb +21 -0
- data/lib/freetype/version.rb +3 -0
- data/lib/freetype_test.rb +1 -0
- metadata +121 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'freetype/api'
|
2
|
+
|
3
|
+
module FreeTypeApiTest
|
4
|
+
include FreeType::API
|
5
|
+
|
6
|
+
def libopen
|
7
|
+
Library.open do |lib|
|
8
|
+
['data/Prida01.otf', 'data/Starjedi.ttf'].each do |font|
|
9
|
+
lib.face_open(font) do |f|
|
10
|
+
f.set_char_size(0, 0, 300, 300)
|
11
|
+
yield f
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_Library(t)
|
18
|
+
lib = nil
|
19
|
+
ret = Library.open do |l|
|
20
|
+
lib = l
|
21
|
+
|
22
|
+
unless /\A\d+\.\d+\.\d+\z/.match l.version
|
23
|
+
t.error "return value break got #{l.version}"
|
24
|
+
end
|
25
|
+
|
26
|
+
:abc
|
27
|
+
end
|
28
|
+
if lib.nil?
|
29
|
+
t.error('cannot get FT_Library in `open` with block')
|
30
|
+
end
|
31
|
+
if ret != :abc
|
32
|
+
t.error 'want to return last value in block'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_Face(t)
|
37
|
+
face = nil
|
38
|
+
Library.open do |lib|
|
39
|
+
['data/Prida01.otf', 'data/Starjedi.ttf'].each do |font|
|
40
|
+
lib.face_open(font) do |f|
|
41
|
+
face = f
|
42
|
+
if f.char_index('a') == 0
|
43
|
+
t.error('ascii char not defined this font')
|
44
|
+
end
|
45
|
+
if f.char_index('㍿') != 0
|
46
|
+
t.error("I don't know why set character was defined in font")
|
47
|
+
end
|
48
|
+
|
49
|
+
v = f.kerning('A', 'W')
|
50
|
+
unless v
|
51
|
+
t.error('#kerning return object was changed')
|
52
|
+
end
|
53
|
+
unless Fixnum === v.x && Fixnum === v.y
|
54
|
+
t.error('Not vector object. Check spec for FT_Get_Kerning()')
|
55
|
+
end
|
56
|
+
|
57
|
+
if /darwin/ =~ RUBY_PLATFORM
|
58
|
+
begin
|
59
|
+
err = StringIO.new
|
60
|
+
origerr = $stderr
|
61
|
+
$stderr = err
|
62
|
+
f.glyph('a')
|
63
|
+
rescue FreeType::Error::Invalid_Size_Handle
|
64
|
+
if err.string.empty?
|
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
|
89
|
+
end
|
90
|
+
end
|
91
|
+
if face.nil?
|
92
|
+
t.error('cannot get FT_Face in `open` with block')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_glyph(t)
|
97
|
+
libopen do |f|
|
98
|
+
table = { 'a' => nil, 'b' => nil, 'c' => nil, 'd' => nil }
|
99
|
+
table.each do |char, _|
|
100
|
+
glyph = f.glyph(char)
|
101
|
+
|
102
|
+
metrics = glyph.metrics
|
103
|
+
unless FreeType::C::FT_Glyph_Metrics === metrics
|
104
|
+
t.error 'return value was break'
|
105
|
+
end
|
106
|
+
|
107
|
+
space_width = glyph.space_width
|
108
|
+
unless Fixnum === space_width
|
109
|
+
t.error 'return value was break'
|
110
|
+
end
|
111
|
+
|
112
|
+
outline = glyph.outline
|
113
|
+
unless Outline === outline
|
114
|
+
t.error('FreeType::API::Face#outline return value was break')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_outline(t)
|
121
|
+
libopen do |f|
|
122
|
+
table = { 'a' => nil, 'b' => nil, 'c' => nil, 'd' => nil }
|
123
|
+
table.each do |char, _|
|
124
|
+
outline = f.glyph(char).outline
|
125
|
+
|
126
|
+
unless 0 < outline.points.length
|
127
|
+
t.error('FT_Outline.points get failed from ffi')
|
128
|
+
end
|
129
|
+
|
130
|
+
unless outline.points.all? { |i| Point === i }
|
131
|
+
t.error('Miss array of FreeType::API::Outline#points objects assignment')
|
132
|
+
end
|
133
|
+
|
134
|
+
unless outline.tags.all? { |i| Fixnum === i }
|
135
|
+
t.error('Got values miss assigned from ffi')
|
136
|
+
end
|
137
|
+
|
138
|
+
unless outline.contours.all? { |i| Fixnum === i }
|
139
|
+
t.error('Got values miss assigned from ffi')
|
140
|
+
end
|
141
|
+
|
142
|
+
table[char] = outline.points.map(&:x)
|
143
|
+
end
|
144
|
+
if table.values.uniq.length != table.length
|
145
|
+
t.error 'char reference miss'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/freetype/c.rb
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FreeType
|
4
|
+
# low level APIs call by FFI
|
5
|
+
module C
|
6
|
+
extend ::FFI::Library
|
7
|
+
ffi_lib ['libfreetype.dylib', 'libfreetype.6.dylib', 'freetype.so', 'freetype.so.6', 'freetype']
|
8
|
+
typedef :long, :FT_Pos
|
9
|
+
typedef :long, :FT_Fixed
|
10
|
+
typedef :long, :FT_F26Dot6
|
11
|
+
typedef :int, :FT_Error
|
12
|
+
|
13
|
+
FT_ENC_TAG = lambda do |a, b, c, d|
|
14
|
+
[a, b, c, d].map(&:ord).inject(0) { |r, i| (r << 8) + i }
|
15
|
+
end
|
16
|
+
|
17
|
+
FT_IMAGE_TAG = FT_ENC_TAG
|
18
|
+
|
19
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Glyph_Format
|
20
|
+
FT_Glyph_Format = enum(
|
21
|
+
:FT_GLYPH_FORMAT_NONE, 0,
|
22
|
+
:FT_GLYPH_FORMAT_COMPOSITE, FT_IMAGE_TAG['c', 'o', 'm', 'p'],
|
23
|
+
:FT_GLYPH_FORMAT_BITMAP, FT_IMAGE_TAG['b', 'i', 't', 's'],
|
24
|
+
:FT_GLYPH_FORMAT_OUTLINE, FT_IMAGE_TAG['o', 'u', 't', 'l'],
|
25
|
+
:FT_GLYPH_FORMAT_PLOTTER, FT_IMAGE_TAG['p', 'l', 'o', 't'],
|
26
|
+
)
|
27
|
+
|
28
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Kerning_Mode
|
29
|
+
FT_Kerning_Mode = enum(
|
30
|
+
:FT_KERNING_DEFAULT, 0,
|
31
|
+
:FT_KERNING_UNFITTED,
|
32
|
+
:FT_KERNING_UNSCALED,
|
33
|
+
)
|
34
|
+
|
35
|
+
FT_Encoding = enum(
|
36
|
+
:FT_ENCODING_NONE, 0,
|
37
|
+
:FT_ENCODING_MS_SYMBOL, FT_ENC_TAG['s', 'y', 'm', 'b'],
|
38
|
+
:FT_ENCODING_UNICODE, FT_ENC_TAG['u', 'n', 'i', 'c'],
|
39
|
+
:FT_ENCODING_SJIS, FT_ENC_TAG['s', 'j', 'i', 's'],
|
40
|
+
:FT_ENCODING_GB2312, FT_ENC_TAG['g', 'b', ' ', ' '],
|
41
|
+
:FT_ENCODING_BIG5, FT_ENC_TAG['b', 'i', 'g', '5'],
|
42
|
+
:FT_ENCODING_WANSUNG, FT_ENC_TAG['w', 'a', 'n', 's'],
|
43
|
+
:FT_ENCODING_JOHAB, FT_ENC_TAG['j', 'o', 'h', 'a'],
|
44
|
+
:FT_ENCODING_ADOBE_STANDARD, FT_ENC_TAG['A', 'D', 'O', 'B'],
|
45
|
+
:FT_ENCODING_ADOBE_EXPERT, FT_ENC_TAG['A', 'D', 'B', 'E'],
|
46
|
+
:FT_ENCODING_ADOBE_CUSTOM, FT_ENC_TAG['A', 'D', 'B', 'C'],
|
47
|
+
:FT_ENCODING_ADOBE_LATIN_1, FT_ENC_TAG['l', 'a', 't', '1'],
|
48
|
+
:FT_ENCODING_OLD_LATIN_2, FT_ENC_TAG['l', 'a', 't', '2'],
|
49
|
+
:FT_ENCODING_APPLE_ROMAN, FT_ENC_TAG['a', 'r', 'm', 'n'],
|
50
|
+
)
|
51
|
+
|
52
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_LOAD_XXX
|
53
|
+
FT_LOAD_DEFAULT = 0x0
|
54
|
+
FT_LOAD_NO_SCALE = 1 << 0
|
55
|
+
FT_LOAD_NO_HINTING = 1 << 1
|
56
|
+
FT_LOAD_RENDER = 1 << 2
|
57
|
+
FT_LOAD_NO_BITMAP = 1 << 3
|
58
|
+
FT_LOAD_VERTICAL_LAYOUT = 1 << 4
|
59
|
+
FT_LOAD_FORCE_AUTOHINT = 1 << 5
|
60
|
+
FT_LOAD_CROP_BITMAP = 1 << 6
|
61
|
+
FT_LOAD_PEDANTIC = 1 << 7
|
62
|
+
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = 1 << 9
|
63
|
+
FT_LOAD_NO_RECURSE = 1 << 10
|
64
|
+
FT_LOAD_IGNORE_TRANSFORM = 1 << 11
|
65
|
+
FT_LOAD_MONOCHROME = 1 << 12
|
66
|
+
FT_LOAD_LINEAR_DESIGN = 1 << 13
|
67
|
+
FT_LOAD_NO_AUTOHINT = 1 << 15
|
68
|
+
FT_LOAD_COLOR = 1 << 20
|
69
|
+
FT_LOAD_COMPUTE_METRICS = 1 << 21
|
70
|
+
|
71
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_BBox
|
72
|
+
class FT_BBox < ::FFI::Struct
|
73
|
+
layout xMin: :FT_Pos,
|
74
|
+
yMin: :FT_Pos,
|
75
|
+
xMax: :FT_Pos,
|
76
|
+
yMax: :FT_Pos
|
77
|
+
end
|
78
|
+
|
79
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Bitmap
|
80
|
+
class FT_Bitmap < ::FFI::Struct
|
81
|
+
layout rows: :uint,
|
82
|
+
width: :uint,
|
83
|
+
pitch: :int,
|
84
|
+
buffer: :pointer,
|
85
|
+
num_grays: :ushort,
|
86
|
+
pixel_mode: :char,
|
87
|
+
palette_mode: :char,
|
88
|
+
palette: :pointer
|
89
|
+
end
|
90
|
+
|
91
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Generic
|
92
|
+
class FT_Generic < ::FFI::Struct
|
93
|
+
layout data: :pointer,
|
94
|
+
finalizer: :pointer
|
95
|
+
end
|
96
|
+
|
97
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Glyph_Metrics
|
98
|
+
class FT_Glyph_Metrics < ::FFI::Struct
|
99
|
+
layout width: :FT_Pos,
|
100
|
+
height: :FT_Pos,
|
101
|
+
horiBearingX: :FT_Pos,
|
102
|
+
horiBearingY: :FT_Pos,
|
103
|
+
horiAdvance: :FT_Pos,
|
104
|
+
vertBearingX: :FT_Pos,
|
105
|
+
vertBearingY: :FT_Pos,
|
106
|
+
vertAdvance: :FT_Pos
|
107
|
+
end
|
108
|
+
|
109
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline
|
110
|
+
class FT_Outline < ::FFI::Struct
|
111
|
+
layout n_contours: :short,
|
112
|
+
n_points: :short,
|
113
|
+
points: :pointer, # FT_Vector* (n_points)
|
114
|
+
tags: :pointer, # char * (n_points)
|
115
|
+
contours: :pointer, # short * (n_contours)
|
116
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_OUTLINE_XXX
|
117
|
+
flags: :int
|
118
|
+
end
|
119
|
+
|
120
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Vector
|
121
|
+
class FT_Vector < ::FFI::Struct
|
122
|
+
layout x: :FT_Pos,
|
123
|
+
y: :FT_Pos
|
124
|
+
end
|
125
|
+
|
126
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_GlyphSlotRec
|
127
|
+
class FT_GlyphSlotRec < ::FFI::Struct
|
128
|
+
layout library: :pointer,
|
129
|
+
face: :pointer,
|
130
|
+
next: :pointer,
|
131
|
+
reserved: :uint,
|
132
|
+
generic: FT_Generic,
|
133
|
+
metrics: FT_Glyph_Metrics,
|
134
|
+
linearHoriAdvance: :FT_Fixed,
|
135
|
+
linearVertAdvance: :FT_Fixed,
|
136
|
+
advance: FT_Vector,
|
137
|
+
format: FT_Glyph_Format,
|
138
|
+
bitmap: FT_Bitmap,
|
139
|
+
bitmap_left: :int,
|
140
|
+
bitmap_top: :int,
|
141
|
+
outline: FT_Outline,
|
142
|
+
num_subglyphs: :uint,
|
143
|
+
subglyphs: :pointer, # FT_SubGlyph
|
144
|
+
control_data: :pointer, # void *
|
145
|
+
control_len: :long,
|
146
|
+
lsb_delta: :FT_Pos,
|
147
|
+
rsb_delta: :FT_Pos,
|
148
|
+
other: :pointer, # void *
|
149
|
+
internal: :pointer # FT_Slot_Internal
|
150
|
+
end
|
151
|
+
|
152
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Size_Metrics
|
153
|
+
class FT_Size_Metrics < ::FFI::Struct
|
154
|
+
layout x_ppem: :ushort,
|
155
|
+
y_ppem: :ushort,
|
156
|
+
x_scale: :FT_Fixed,
|
157
|
+
y_scale: :FT_Fixed,
|
158
|
+
ascender: :FT_Pos,
|
159
|
+
descender: :FT_Pos,
|
160
|
+
height: :FT_Pos,
|
161
|
+
max_advance: :FT_Pos
|
162
|
+
end
|
163
|
+
|
164
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_SizeRec
|
165
|
+
class FT_SizeRec < ::FFI::Struct
|
166
|
+
layout face: :pointer, # FT_Face
|
167
|
+
generic: FT_Generic,
|
168
|
+
metrics: FT_Size_Metrics,
|
169
|
+
internal: :pointer # FT_Size_Internal
|
170
|
+
end
|
171
|
+
|
172
|
+
class FT_CharMapRec < ::FFI::Struct
|
173
|
+
layout face: :pointer,
|
174
|
+
encoding: FT_Encoding,
|
175
|
+
platform_id: :ushort,
|
176
|
+
encoding_id: :ushort
|
177
|
+
end
|
178
|
+
|
179
|
+
# http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
|
180
|
+
class FT_FaceRec < ::FFI::Struct
|
181
|
+
layout num_faces: :long,
|
182
|
+
face_index: :long,
|
183
|
+
face_flags: :long,
|
184
|
+
style_flags: :long,
|
185
|
+
num_glyphs: :long,
|
186
|
+
family_name: :string,
|
187
|
+
style_name: :string,
|
188
|
+
num_fixed_sizes: :int,
|
189
|
+
available_sizes: :pointer, # FT_Bitmap_Size*
|
190
|
+
num_charmaps: :int,
|
191
|
+
charmaps: FT_CharMapRec.ptr,
|
192
|
+
generic: FT_Generic,
|
193
|
+
bbox: FT_BBox,
|
194
|
+
units_per_EM: :ushort,
|
195
|
+
ascender: :short,
|
196
|
+
descender: :short,
|
197
|
+
height: :short,
|
198
|
+
max_advance_width: :short,
|
199
|
+
max_advance_height: :short,
|
200
|
+
underline_position: :short,
|
201
|
+
underline_thickness: :short,
|
202
|
+
glyph: FT_GlyphSlotRec.ptr,
|
203
|
+
size: FT_SizeRec.ptr,
|
204
|
+
charmap: :pointer
|
205
|
+
end
|
206
|
+
|
207
|
+
# library = FFI::MemoryPointer.new(:pointer)
|
208
|
+
# err = FT_Init_FreeType(library)
|
209
|
+
# err = FT_Done_Library(library.get_pointer(0))
|
210
|
+
attach_function :FT_Init_FreeType, [:pointer], :FT_Error
|
211
|
+
attach_function :FT_Done_Library, [:pointer], :FT_Error
|
212
|
+
attach_function :FT_Library_Version, [:pointer, :pointer, :pointer, :pointer], :void
|
213
|
+
|
214
|
+
# face = FFI::MemoryPointer.new(:pointer)
|
215
|
+
# err = FT_New_Face(library.get_pointer(0), 'font.otf', 0, face)
|
216
|
+
# face = FT_FaceRec.new(face.get_pointer(0))
|
217
|
+
# err = FT_Done_Face(face)
|
218
|
+
attach_function :FT_New_Face, [:pointer, :string, :long, :pointer], :FT_Error
|
219
|
+
attach_function :FT_Done_Face, [:pointer], :FT_Error
|
220
|
+
|
221
|
+
# err = FT_Set_Char_Size(face, 0, 36 * 64, 300, 300)
|
222
|
+
attach_function :FT_Set_Char_Size, [:pointer, :FT_F26Dot6, :FT_F26Dot6, :uint, :uint], :FT_Error
|
223
|
+
|
224
|
+
# err = FT_Select_Charmap(face, :FT_ENCODING_UNICODE)
|
225
|
+
attach_function :FT_Select_Charmap, [:pointer, FT_Encoding], :FT_Error
|
226
|
+
|
227
|
+
# err = FT_Load_Char(face, 'Q'.ord, FreeType::FT_LOAD_DEFAULT)
|
228
|
+
attach_function :FT_Load_Char, [:pointer, :ulong, :int32], :FT_Error
|
229
|
+
|
230
|
+
# err = FT_Load_Glyph(face, 0, FT_LOAD_DEFAULT)
|
231
|
+
# attach_function :FT_Load_Glyph, [FT_FaceRec.ptr, :uint, :int32], :FT_Error
|
232
|
+
# attach_function :FT_Get_Glyph, [FT_GlyphSlotRec.ptr, :pointer], :FT_Error
|
233
|
+
# attach_function :FT_Done_Glyph, [:pointer], :void
|
234
|
+
|
235
|
+
# id = FT_Get_Char_Index(face, 'A'.ord) -> glyph id or 0 (undefined)
|
236
|
+
attach_function :FT_Get_Char_Index, [:pointer, :ulong], :uint
|
237
|
+
|
238
|
+
# v = FT_Vector.new
|
239
|
+
# err = FT_Get_Kerning(face, before_id, id, :FT_KERNING_DEFAULT, v)
|
240
|
+
# p v
|
241
|
+
attach_function :FT_Get_Kerning, [:pointer, :uint, :uint, :uint, :pointer], :FT_Error
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'freetype/c'
|
2
|
+
|
3
|
+
module FFITest
|
4
|
+
include FreeType::C
|
5
|
+
|
6
|
+
FONTS = ['data/Prida01.otf', 'data/Starjedi.ttf']
|
7
|
+
|
8
|
+
def libopen
|
9
|
+
library = ::FFI::MemoryPointer.new(:pointer)
|
10
|
+
err = FT_Init_FreeType(library)
|
11
|
+
raise FreeType::Error.find(err) unless err == 0
|
12
|
+
|
13
|
+
FONTS.each do |font|
|
14
|
+
face = ::FFI::MemoryPointer.new(:pointer)
|
15
|
+
err = FT_New_Face(library.get_pointer(0), font, 0, face)
|
16
|
+
raise FreeType::Error.find(err) unless err == 0
|
17
|
+
|
18
|
+
yield FT_FaceRec.new(face.get_pointer(0)), font
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_Library(t)
|
23
|
+
library = ::FFI::MemoryPointer.new(:pointer)
|
24
|
+
err = FT_Init_FreeType(library)
|
25
|
+
if err != 0
|
26
|
+
t.fatal FreeType::Error.find(err).message
|
27
|
+
end
|
28
|
+
|
29
|
+
amajor = FFI::MemoryPointer.new(:int)
|
30
|
+
aminor = FFI::MemoryPointer.new(:int)
|
31
|
+
apatch = FFI::MemoryPointer.new(:int)
|
32
|
+
FT_Library_Version(library.get_pointer(0), amajor, aminor, apatch)
|
33
|
+
a = [
|
34
|
+
amajor.get_int(0),
|
35
|
+
aminor.get_int(0),
|
36
|
+
apatch.get_int(0),
|
37
|
+
]
|
38
|
+
unless a.all? { |i| Fixnum === i }
|
39
|
+
t.error 'miss get values from FT_Library_Version()'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_Face(t)
|
44
|
+
library = ::FFI::MemoryPointer.new(:pointer)
|
45
|
+
err = FT_Init_FreeType(library)
|
46
|
+
if err != 0
|
47
|
+
t.fatal FreeType::Error.find(err).message
|
48
|
+
end
|
49
|
+
FONTS.each do |font|
|
50
|
+
face = ::FFI::MemoryPointer.new(:pointer)
|
51
|
+
err = FT_New_Face(library.get_pointer(0), font, 0, face)
|
52
|
+
if err != 0
|
53
|
+
t.fatal FreeType::Error.find(err).message
|
54
|
+
end
|
55
|
+
|
56
|
+
face = FT_FaceRec.new(face.get_pointer(0))
|
57
|
+
err = FT_Select_Charmap(face, :FT_ENCODING_UNICODE)
|
58
|
+
if err != 0
|
59
|
+
t.error FreeType::Error.find(err).message
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_FT_Set_Char_Size(t)
|
65
|
+
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
|
+
err = FT_Set_Char_Size(face, 0, 32, 300, 300)
|
75
|
+
if err != 0
|
76
|
+
t.error FreeType::Error.find(err).message
|
77
|
+
end
|
78
|
+
|
79
|
+
err = FT_Load_Char(face, 'a'.ord, FreeType::C::FT_LOAD_DEFAULT)
|
80
|
+
if err != 0
|
81
|
+
t.error FreeType::Error.find(err).message
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_char(t)
|
87
|
+
libopen do |face, _font|
|
88
|
+
err = FT_Set_Char_Size(face, 0, 32, 300, 300)
|
89
|
+
if err != 0
|
90
|
+
t.fatal FreeType::Error.find(err).message
|
91
|
+
end
|
92
|
+
|
93
|
+
before_glyph_id = nil
|
94
|
+
%w(i e f g A W & * @ % - + < >).concat([' ', 'あ', ' ', "\n"]).each do |char|
|
95
|
+
glyph_id = FT_Get_Char_Index(face, char.ord)
|
96
|
+
if glyph_id == 0
|
97
|
+
unless /あ| |\n/.match(char)
|
98
|
+
t.error('ascii char is undefined')
|
99
|
+
end
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
103
|
+
if before_glyph_id
|
104
|
+
v = FT_Vector.new
|
105
|
+
err = FT_Get_Kerning(face, before_glyph_id, glyph_id, :FT_KERNING_UNFITTED, v)
|
106
|
+
if err != 0
|
107
|
+
t.error FreeType::Error.find(err).message
|
108
|
+
end
|
109
|
+
unless Fixnum === v[:x] && Fixnum === v[:y]
|
110
|
+
t.error 'cannot get kerning value from FT_Get_Kerning()'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
err = FT_Load_Char(face, char.ord, FreeType::C::FT_LOAD_DEFAULT)
|
115
|
+
if err != 0
|
116
|
+
t.error FreeType::Error.find(err).message
|
117
|
+
end
|
118
|
+
|
119
|
+
size = face[:size]
|
120
|
+
unless FT_SizeRec === size
|
121
|
+
t.error 'Miss Struct bind'
|
122
|
+
end
|
123
|
+
|
124
|
+
size_metrics = face[:size][:metrics]
|
125
|
+
unless FT_Size_Metrics === size_metrics
|
126
|
+
t.error 'Miss Struct bind'
|
127
|
+
end
|
128
|
+
|
129
|
+
glyph = face[:glyph]
|
130
|
+
unless FT_GlyphSlotRec === glyph
|
131
|
+
t.error 'Miss Struct bind'
|
132
|
+
end
|
133
|
+
|
134
|
+
glyph_metrics = face[:glyph][:metrics]
|
135
|
+
unless FT_Glyph_Metrics === glyph_metrics
|
136
|
+
t.error 'Miss Struct bind'
|
137
|
+
end
|
138
|
+
|
139
|
+
outline = face[:glyph][:outline]
|
140
|
+
unless 0 <= outline[:n_points]
|
141
|
+
t.error "n_outline:#{outline[:n_points]} Cannot get FT_Outline.n_prints member from ffi"
|
142
|
+
end
|
143
|
+
|
144
|
+
unless 0 <= outline[:n_contours]
|
145
|
+
t.error "n_contours:#{outline[:n_contours]} Cannot get FT_Outline.n_contours member from ffi"
|
146
|
+
end
|
147
|
+
|
148
|
+
end_ptd_of_counts = outline[:contours].get_array_of_short(0, outline[:n_contours])
|
149
|
+
|
150
|
+
unless end_ptd_of_counts.all? { |i| Fixnum === i }
|
151
|
+
t.error 'FT_Outline.contours is array if short. broken or fail when get form ffi.'
|
152
|
+
end
|
153
|
+
|
154
|
+
tags = outline[:tags].get_array_of_char(0, outline[:n_points])
|
155
|
+
unless tags.all? { |i| Fixnum === i }
|
156
|
+
t.error 'FT_Outline.tags is array of char. broken or fail when get form ffi.'
|
157
|
+
end
|
158
|
+
|
159
|
+
points = outline[:n_points].times.map do |i|
|
160
|
+
FT_Vector.new(outline[:points] + i * FT_Vector.size)
|
161
|
+
end
|
162
|
+
|
163
|
+
points.each do |i|
|
164
|
+
unless i[:x].kind_of?(Fixnum) && i[:y].kind_of?(Fixnum)
|
165
|
+
t.error('Miss assignment from ffi')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
before_glyph_id = glyph_id
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|