freetype 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|