ft2-ruby 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ Thu Aug 15 09:39:24 2002, pabs <pabs@pablotron.org>
2
+ * created changelog.
3
+
4
+ Tue Nov 12 17:20:23 2002, pabs <pabs@pablotron.org
5
+ * made some changes according to the notes in the freetype2 headers:
6
+ * ft2.c: removed FT2::PixelMode::RGB and FT2::PixelMode::RGBA constants
7
+ * ft2.c: removed Ft2::PaletteMode
8
+ * compiles clean with -W -Wall -pedantic again
9
+
10
+ Fri Nov 15 03:27:50 2002, pabs <pabs@pablotron.org
11
+ * ft2.c: finished documentation for FT2::Face methods.
12
+
13
+ Fri Nov 15 03:52:46 2002, pabs <pabs@pablotron.org
14
+ * ft2.c: added FT2::Face#current_charmap
15
+
16
+ Fri Nov 15 15:15:37 2002, pabs <pabs@pablotron.org
17
+ * ft2.c: finished documentation for FT2::GlyphMetrics methods.
18
+
19
+ Sat Nov 16 01:45:42 2002, pabs <pabs@pablotron.org
20
+ * ft2.c: finished documentation for FT2::GlyphSlot methods.
21
+
22
+ Wed Nov 20 16:11:10 2002, pabs <pabs@pablotron.org
23
+ * ft2.c: finished documenting the FT2::SizeMetrics methods (had to
24
+ pull the documentation for them out of the second part of the
25
+ FreeType2 tutorial, since they're not available in the API
26
+ reference).
27
+
28
+ Thu Nov 21 15:18:26 2002, pabs <pabs@pablotron.org
29
+ * ft2.c: finished documenting and implementing FT2::Glyph,
30
+ FT2::BitmapGlyph, and FT2::OutlineGlyph.
31
+ * ft2.c: compiles clean with -W -Wall -pedantic again
32
+ * TODO: updated
@@ -0,0 +1,14 @@
1
+ ./README
2
+ ./ft2.c
3
+ ./extconf.rb
4
+ ./examples/name_list.rb
5
+ ./examples/test_ft2.rb
6
+ ./examples/fonts/CVS/Root
7
+ ./examples/fonts/CVS/Repository
8
+ ./examples/fonts/CVS/Entries
9
+ ./examples/fonts/yudit.ttf
10
+ ./examples/.test_ft2.rb.swp
11
+ ./MANIFEST
12
+ ./TODO
13
+ ./tags
14
+ ./ChangeLog
data/README ADDED
@@ -0,0 +1,19 @@
1
+ FT2-Ruby 0.1.0 README
2
+ =====================
3
+
4
+ This document was last updated on Sat Nov 16 17:51:41 2002. Please see
5
+ http://www.pablotron.org/software/ft2-ruby/ for the latest version of
6
+ this software.
7
+
8
+ Introduction
9
+ ============
10
+ hum de dum dum
11
+
12
+ Installing FT2-Ruby
13
+ ===================
14
+ blah de blah blah
15
+
16
+ About the Author
17
+ ================
18
+ Paul Duncan <pabs@pablotron.org>
19
+ http://www.pablotron.org/
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ft2-ruby"
8
+ gem.summary = %Q{Ruby libraries to FreeType2}
9
+ gem.email = "pabs@pablotron.org"
10
+ gem.homepage = "http://www.pablotron.org/"
11
+ gem.authors = ["Paul Duncan"]
12
+ gem.extensions = ["extconf.rb"]
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
+ end
19
+
20
+ #
21
+ # task :default => :test
22
+ #
23
+ require 'rake/rdoctask'
24
+ Rake::RDocTask.new do |rdoc|
25
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
26
+
27
+ rdoc.rdoc_dir = 'rdoc'
28
+ rdoc.title = "ft2-ruby #{version}"
29
+ rdoc.rdoc_files.include('README')
30
+ rdoc.rdoc_files.include('TODO')
31
+ rdoc.rdoc_files.include('ft2.c')
32
+ end
data/TODO ADDED
@@ -0,0 +1,3 @@
1
+ * fixed point data conversions
2
+ * face subglyph handling
3
+ * test test test test!
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
Binary file
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $FONTDIR = '/usr/X11R6/lib/X11/fonts/truetype'
4
+
5
+ require 'readline'
6
+ require 'ft2'
7
+
8
+ $commands = {
9
+ 'quit' => 'Quit program.',
10
+ 'list' => 'List all fonts.',
11
+ 'help' => 'Print this list of commands.',
12
+ }
13
+ $fonts = {}
14
+
15
+ def tab_complete(str)
16
+ ($commands.keys.map { |i| i =~ /^#{str}/i ? i : nil }.compact! || []) +
17
+ $fonts.keys.map { |i| i =~ /^#{str}/i ? i : nil }.compact!
18
+ end
19
+
20
+ def show_font_info(str)
21
+ path, face = $fonts[str]
22
+ if path and face
23
+ puts 'Name: ' << face.name,
24
+ 'Path: ' << path,
25
+ 'Family: ' << face.family,
26
+ 'Style: ' << face.style,
27
+ 'Bold: ' << face.bold?.to_s,
28
+ 'Italic: ' << face.italic?.to_s,
29
+ 'Scalable: ' << face.scalable?.to_s,
30
+ 'Horizontal: ' << face.horizontal?.to_s,
31
+ 'Vertical: ' << face.vertical?.to_s,
32
+ 'Kerning: ' << face.kerning?.to_s,
33
+ 'Fast Glyphs: ' << face.fast_glyphs?.to_s,
34
+ 'Num Glyphs: ' << face.num_glyphs.to_s,
35
+ 'Num Charmaps: ' << face.num_charmaps.to_s
36
+
37
+ else
38
+ $stderr.puts "Unknown font \"#{str}\""
39
+ end
40
+ end
41
+
42
+ count = 0
43
+ Dir["#$FONTDIR/*"].each { |i|
44
+ count += 1
45
+ next if i =~ /^\./
46
+ begin
47
+ face = FT2::Face.load(i)
48
+ rescue Exception
49
+ next
50
+ end
51
+ # puts [face, face.name, face.num_glyphs ].join ', '
52
+ $fonts[face.name] = [i, face]
53
+ }
54
+ puts "Loaded #{$fonts.keys.size} of #{count} fonts."
55
+
56
+ # Readline::completion_case_fold = true
57
+ Readline::completion_proc = Proc.new { |str| tab_complete(str) }
58
+
59
+ done = false
60
+ until done
61
+ line = Readline::readline '> ', true
62
+
63
+ case line
64
+ when %r|^q(uit)?|
65
+ done = true
66
+ when %r|^h(elp)?|
67
+ $commands.keys.sort { |a, b| a <=> b }.each { |key|
68
+ puts "#{key}: #{$commands[key]}"
69
+ }
70
+ when %r|^l(ist\|s)?|
71
+ $fonts.each { |key, val|
72
+ path, face = val
73
+ puts [key, face.num_glyphs].join ', '
74
+ }
75
+ when /^$/
76
+ next
77
+ else
78
+ show_font_info(line.strip)
79
+ end
80
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ft2'
4
+
5
+ puts FT2::version
6
+ puts FT2::VERSION
7
+
8
+ face = FT2::Face.new 'fonts/yudit.ttf'
9
+ puts "glyphs: #{face.glyphs}",
10
+ "charmaps: #{face.num_charmaps}",
11
+ "horiz: #{face.horizontal?}",
12
+ "vert: #{face.vertical?}"
13
+
14
+ # cycle through default charmap
15
+ puts 'listing character codes with first_char/next_char'
16
+ c_code, g_idx = face.first_char
17
+ while g_idx != 0
18
+ puts "#{c_code} => " << face.glyph_name(g_idx)
19
+ c_code, g_idx = face.next_char c_code
20
+ end
21
+
22
+ puts 'listing charcodes with current_charmap'
23
+
24
+ cmap = face.current_charmap
25
+ cmap.keys.sort.each { |c_code|
26
+ puts "#{c_code} => " << face.glyph_name(cmap[c_code])
27
+ }
@@ -0,0 +1,10 @@
1
+ require 'mkmf'
2
+
3
+ ft2_config = with_config("freetype-config", "freetype-config")
4
+
5
+ $CFLAGS << ' ' << `#{ft2_config} --cflags`.chomp
6
+ $LDFLAGS << ' ' << `#{ft2_config} --libs`.chomp
7
+
8
+ have_library("freetype", "FT_Init_FreeType") and
9
+ create_makefile("ft2")
10
+
data/ft2.c ADDED
@@ -0,0 +1,3170 @@
1
+ /************************************************************************/
2
+ /* Copyright (c) 2002 Paul Duncan */
3
+ /* */
4
+ /* Permission is hereby granted, free of charge, to any person */
5
+ /* obtaining a copy of this software and associated documentation files */
6
+ /* (the "Software"), to deal in the Software without restriction, */
7
+ /* including without limitation the rights to use, copy, modify, merge, */
8
+ /* publish, distribute, sublicense, and/or sell copies of the Software, */
9
+ /* and to permit persons to whom the Software is furnished to do so, */
10
+ /* subject to the following conditions: */
11
+ /* */
12
+ /* The above copyright notice and this permission notice shall be */
13
+ /* included in all copies of the Software, its documentation and */
14
+ /* marketing & publicity materials, and acknowledgment shall be given */
15
+ /* in the documentation, materials and software packages that this */
16
+ /* Software was used. */
17
+ /* */
18
+ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
19
+ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
20
+ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
21
+ /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY */
22
+ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
23
+ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
24
+ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25
+ /************************************************************************/
26
+
27
+ #include <ruby.h>
28
+ #include <ft2build.h>
29
+ #include FT_FREETYPE_H
30
+ #include FT_GLYPH_H
31
+
32
+ #define VERSION "0.1.0"
33
+ #define UNUSED(a) ((void) (a))
34
+ #define ABS(a) (((a) < 0) ? -(a) : (a))
35
+
36
+ /* convert to and from FT2 fixed values */
37
+ #define FTFIX2DBL(a) ((double) (a) / 0x10000)
38
+ #define DBL2FTFIX(a) ((double) (a) * 0x10000)
39
+
40
+ static FT_Library library;
41
+ static VALUE mFt2,
42
+ mBBox, /* GlyphBBox */
43
+ mEnc, /* encoding */
44
+ mGlyphFormat,
45
+ mKerningMode,
46
+ mLoad,
47
+ /* mPaletteMode, */
48
+ mPixelMode,
49
+ mRenderMode,
50
+
51
+ cBitmap,
52
+ cBitmapGlyph,
53
+ cCharMap,
54
+ cFace,
55
+ cGlyph,
56
+ cGlyphClass,
57
+ cGlyphSlot,
58
+ cGlyphMetrics,
59
+ cLibrary,
60
+ cMemory,
61
+ cOutline,
62
+ cOutlineGlyph,
63
+ /* cRaster, */
64
+ cSubGlyph,
65
+ cSize,
66
+ cSizeMetrics;
67
+
68
+ static void face_free(void *ptr);
69
+ static void glyph_free(void *ptr);
70
+
71
+ static void dont_free(void *ptr) { UNUSED(ptr); }
72
+
73
+ static void handle_error(FT_Error err) {
74
+ #undef __FTERRORS_H__
75
+ #define FT_ERRORDEF( e, v, s ) { e, s },
76
+ #define FT_ERROR_START_LIST {
77
+ #define FT_ERROR_END_LIST { 0, 0 } };
78
+ int i = 0;
79
+ static const struct {
80
+ int code;
81
+ const char *str;
82
+ } errors[] =
83
+ #include FT_ERRORS_H
84
+
85
+ for (i = 0; ((unsigned int) i) < sizeof(errors) / sizeof(errors[0]); i++)
86
+ if (err == errors[i].code)
87
+ rb_raise(rb_eException, "FreeType2 Error: %s.", errors[i].str);
88
+
89
+ rb_raise(rb_eException, "FreeType2 Error: Unknown error %d.", err);
90
+ }
91
+
92
+ static double ft_fixed_to_double(FT_Fixed fixed) {
93
+ return ((0xffff0000 & fixed) >> 16) +
94
+ ((double) (0xffff & fixed) / 0xffff);
95
+ }
96
+
97
+ static VALUE ft_version(VALUE klass) {
98
+ char buf[1024];
99
+ FT_Int ver[3];
100
+ UNUSED(klass);
101
+
102
+ FT_Library_Version(library, &(ver[0]), &(ver[1]), &(ver[2]));
103
+
104
+ snprintf(buf, sizeof(buf), "%d.%d.%d", ver[0], ver[1], ver[2]);
105
+ return rb_str_new2(buf);
106
+ }
107
+
108
+
109
+ /***********************/
110
+ /* FT2::Bitmap methods */
111
+ /***********************/
112
+
113
+ /*
114
+ * Constructor for FT2::Bitmap.
115
+ *
116
+ * This method is currently empty. You should never call this method
117
+ * directly unless you're instantiating a derived class (ie, you know
118
+ * what you're doing).
119
+ *
120
+ */
121
+ static VALUE ft_bitmap_init(VALUE self) {
122
+ return self;
123
+ }
124
+
125
+ /*
126
+ * Return the number of rows in a FT2::Bitmap object.
127
+ *
128
+ * Examples:
129
+ * rows = bitmap.rows
130
+ *
131
+ */
132
+ static VALUE ft_bitmap_rows(VALUE self) {
133
+ FT_Bitmap *bitmap;
134
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
135
+ return INT2FIX(bitmap->rows);
136
+ }
137
+
138
+ /*
139
+ * Return the width of an FT2::Bitmap object.
140
+ *
141
+ * Examples:
142
+ * width = bitmap.width
143
+ *
144
+ */
145
+ static VALUE ft_bitmap_width(VALUE self) {
146
+ FT_Bitmap *bitmap;
147
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
148
+ return INT2FIX(bitmap->width);
149
+ }
150
+
151
+ /*
152
+ * Return the pitch (bytes per row) of an FT2::Bitmap object.
153
+ *
154
+ * Return the pitch (bytes per row, including alignment padding) of an
155
+ * FT2::Bitmap object.
156
+ *
157
+ * Examples:
158
+ * width = bitmap.width
159
+ *
160
+ */
161
+ static VALUE ft_bitmap_pitch(VALUE self) {
162
+ FT_Bitmap *bitmap;
163
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
164
+ return INT2FIX(bitmap->pitch);
165
+ }
166
+
167
+ /*
168
+ * Return the buffer (e.g. raw pixel data) of an FT2::Bitmap object.
169
+ *
170
+ * Examples:
171
+ * # return the rendered pixels as a binary string
172
+ * buffer = bitmap.buffer
173
+ *
174
+ * # assume a render method called render_font(buffer, width, height)
175
+ * render_font(bitmap.buffer, bitmap.width, bitmap.rows)
176
+ *
177
+ */
178
+ static VALUE ft_bitmap_buffer(VALUE self) {
179
+ FT_Bitmap *bitmap;
180
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
181
+ return rb_str_new((char*) bitmap->buffer, ABS(bitmap->pitch) * bitmap->rows);
182
+ }
183
+
184
+ /*
185
+ * Return the number of grays in an FT2::Bitmap object.
186
+ *
187
+ * Note:
188
+ * Only used if Ft2::Bitmap#pixel_mode is FT2::PixelMode::GRAYS.
189
+ *
190
+ * Examples:
191
+ * depth = bitmap.num_grays
192
+ *
193
+ */
194
+ static VALUE ft_bitmap_num_grays(VALUE self) {
195
+ FT_Bitmap *bitmap;
196
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
197
+ return INT2FIX(bitmap->num_grays);
198
+ }
199
+
200
+ /*
201
+ * Return the pixel mode (e.g. bit depth) of an FT2::Bitmap object.
202
+ *
203
+ * Note:
204
+ * Always returns one of the values avaiable in FT2::PixelMode (for a
205
+ * full list, try the following code: "p FT2::PixelMode.constants.sort")
206
+ *
207
+ * Examples:
208
+ * case bitmap.pixel_mode
209
+ * when FT2::PixelMode::RGB32
210
+ * puts "wow that's a lot of colors!"
211
+ * when FT2::PixelMode::MONO
212
+ * puts "time to get a better monitor..."
213
+ * end
214
+ *
215
+ */
216
+ static VALUE ft_bitmap_pixel_mode(VALUE self) {
217
+ FT_Bitmap *bitmap;
218
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
219
+ return INT2FIX(bitmap->pixel_mode);
220
+ }
221
+
222
+ /*
223
+ * Return the palette mode of an FT2::Bitmap object.
224
+ *
225
+ * Note:
226
+ * Always returns one of the values avaiable in FT2::PaletteMode.
227
+ *
228
+ * Examples:
229
+ * case bitmap.palette_mode
230
+ * when FT2::PaletteMode::RGBA
231
+ * puts "we have an alpha channel!"
232
+ * when FT2::PaletteMode::RGB
233
+ * puts "no alpha channel for you"
234
+ * end
235
+ *
236
+ */
237
+ static VALUE ft_bitmap_palette_mode(VALUE self) {
238
+ FT_Bitmap *bitmap;
239
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
240
+ return INT2FIX(bitmap->palette_mode);
241
+ }
242
+
243
+ /*
244
+ * Return the palette of an FT2::Bitmap object.
245
+ *
246
+ * Note:
247
+ * Returns a binary string of RGB or RGBA elements (check
248
+ * FT2::Bitmap#palette_mode to determine which).
249
+ *
250
+ * Examples:
251
+ * case bitmap.palette_mode
252
+ * when FT2::PaletteMode::RGBA
253
+ * rgba_palette_string = bitmap.palette
254
+ * when FT2::PaletteMode::RGB
255
+ * rgb_palette_string = bitmap.palette
256
+ * end
257
+ *
258
+ */
259
+ static VALUE ft_bitmap_palette(VALUE self) {
260
+ FT_Bitmap *bitmap;
261
+ /* int size; */
262
+ Data_Get_Struct(self, FT_Bitmap, bitmap);
263
+
264
+ return Qnil;
265
+ /* FIXME i don't know how big the palette memory is, so i'll just
266
+ * assume it's 256 entries :/
267
+ *
268
+ * none of this shit compiles, so I'm disabling it for now.
269
+ if (bitmap->palette_mode == ft_palette_mode_rgb)
270
+ size = 3 * 256;
271
+ else if (bitmap->palette_mode == ft_palette_mode_rgba)
272
+ size = 4 * 256;
273
+ else
274
+ rb_raise(rb_eException, "Unknown palette mode: %d.",
275
+ INT2FIX(bitmap->palette_mode));
276
+
277
+ return rb_str_new(bitmap->palette, size); */
278
+ }
279
+
280
+ /*********************/
281
+ /* FT2::Face methods */
282
+ /*********************/
283
+ static void face_free(void *ptr) {
284
+ FT_Face face = *((FT_Face *) ptr);
285
+ FT_Error err;
286
+
287
+ if ((err = FT_Done_Face(face)) != FT_Err_Ok)
288
+ handle_error(err);
289
+ free(ptr);
290
+ }
291
+
292
+ /*
293
+ * Allocate and initialize a new FT2::Face object.
294
+ *
295
+ * Note:
296
+ * FreeType2-Ruby creates a new (hidden) FT2::Library instance at
297
+ * runtime, which FT2::Face objects are automatically initialized with
298
+ * if an a library is not specified.
299
+ *
300
+ * Aliases:
301
+ * FT2::Face.load
302
+ *
303
+ * Examples:
304
+ * # load font from file "yudit.ttf"
305
+ * face = FT2::Face.new 'yudit.ttf'
306
+ *
307
+ * # load second face from from file "yudit.ttf"
308
+ * face = FT2::Face.new 'yudit.ttf', 1
309
+ *
310
+ * # load font from file "yudit.ttf" under FT2::Library instance lib
311
+ * face = FT2::Face.new lib, 'yudit.ttf'
312
+ *
313
+ * # load second face from file "yudit.ttf" under FT2::Library instance lib
314
+ * face = FT2::Face.new lib, 'yudit.ttf', 1
315
+ */
316
+ VALUE ft_face_new(int argc, VALUE *argv, VALUE klass) {
317
+ VALUE self, path;
318
+ FT_Library *lib;
319
+ FT_Face *face;
320
+ FT_Error err;
321
+ FT_Long face_index;
322
+
323
+ lib = &library;
324
+ switch (argc) {
325
+ case 1:
326
+ path = argv[0];
327
+ face_index = 0;
328
+ break;
329
+ case 2:
330
+ if (rb_obj_is_kind_of(argv[0], rb_cString)) {
331
+ path = argv[0];
332
+ face_index = NUM2INT(argv[1]);
333
+ } else if (rb_obj_is_kind_of(argv[0], cLibrary)) {
334
+ Data_Get_Struct(argv[0], FT_Library, lib);
335
+ path = argv[0];
336
+ face_index = 0;
337
+ } else {
338
+ rb_raise(rb_eArgError, "Invalid first argument.");
339
+ }
340
+ break;
341
+ case 3:
342
+ Data_Get_Struct(argv[0], FT_Library, lib);
343
+ path = argv[1];
344
+ face_index = NUM2INT(argv[1]);
345
+ break;
346
+ default:
347
+ rb_raise(rb_eArgError, "Invalid argument count: %d.", argc);
348
+ }
349
+
350
+ face = malloc(sizeof(FT_Face));
351
+ err = FT_New_Face(*lib, RSTRING(path)->ptr, face_index, face);
352
+ if (err != FT_Err_Ok)
353
+ handle_error(err);
354
+
355
+ self = Data_Wrap_Struct(klass, 0, face_free, face);
356
+ rb_obj_call_init(self, 0, NULL);
357
+
358
+ return self;
359
+ }
360
+
361
+ /*
362
+ * Allocate and initialize a new FT2::Face object from in-memory buffer.
363
+ *
364
+ * Note:
365
+ * FreeType2-Ruby creates a new (hidden) FT2::Library instance at
366
+ * runtime, which FT2::Face objects are automatically initialized with
367
+ * if an a library is not specified.
368
+ *
369
+ * Examples:
370
+ * # load font from string _buffer_
371
+ * face = FT2::Face.new buffer, buffer_size
372
+ *
373
+ * # load second face from string _buffer_
374
+ * face = FT2::Face.new buffer, buffer_size, 1
375
+ *
376
+ * # load font from string _buffer_ under FT2::Library instance _lib_
377
+ * face = FT2::Face.new lib, buffer, buffer_size
378
+ *
379
+ * # load second face from string _buffer_ under FT2::Library instance _lib_
380
+ * face = FT2::Face.new lib, buffer, buffer_size, 1
381
+ */
382
+ VALUE ft_face_new_from_memory(int argc, VALUE *argv, VALUE klass) {
383
+ VALUE self;
384
+ FT_Library *lib;
385
+ FT_Face *face;
386
+ FT_Error err;
387
+ FT_Long face_index;
388
+ void *mem;
389
+ int len;
390
+
391
+ lib = &library;
392
+ switch (argc) {
393
+ case 2:
394
+ mem = RSTRING(argv[0])->ptr;
395
+ len = NUM2INT(argv[1]);
396
+ face_index = 0;
397
+ break;
398
+ case 3:
399
+ if (rb_obj_is_kind_of(argv[0], rb_cString)) {
400
+ mem = RSTRING(argv[0])->ptr;
401
+ len = NUM2INT(argv[1]);
402
+ face_index = NUM2INT(argv[2]);
403
+ } else if (rb_obj_is_kind_of(argv[0], cLibrary)) {
404
+ Data_Get_Struct(argv[0], FT_Library, lib);
405
+ mem = RSTRING(argv[1])->ptr;
406
+ len = NUM2INT(argv[2]);
407
+ face_index = 0;
408
+ } else {
409
+ rb_raise(rb_eArgError, "Invalid first argument.");
410
+ }
411
+ break;
412
+ case 4:
413
+ Data_Get_Struct(argv[0], FT_Library, lib);
414
+ mem = RSTRING(argv[1])->ptr;
415
+ len = NUM2INT(argv[2]);
416
+ face_index = NUM2INT(argv[3]);
417
+ break;
418
+ default:
419
+ rb_raise(rb_eArgError, "Invalid argument count: %d.", argc);
420
+ }
421
+
422
+ face = malloc(sizeof(FT_Face));
423
+ err = FT_New_Memory_Face(*lib, mem, len, face_index, face);
424
+ if (err != FT_Err_Ok)
425
+ handle_error(err);
426
+
427
+ self = Data_Wrap_Struct(klass, 0, face_free, face);
428
+ rb_obj_call_init(self, 0, NULL);
429
+
430
+ return self;
431
+ }
432
+
433
+ /*
434
+ * Constructor for FT2::Face.
435
+ *
436
+ * This method is currently empty. You should never call this method
437
+ * directly unless you're instantiating a derived class (ie, you know
438
+ * what you're doing).
439
+ *
440
+ */
441
+ static VALUE ft_face_init(VALUE self) {
442
+ return self;
443
+ }
444
+
445
+ /*
446
+ * Return the number of faces in an FT2::Face object.
447
+ *
448
+ * Aliases:
449
+ * FT2::Face#num_faces
450
+ *
451
+ * Examples:
452
+ * num_faces = face.faces
453
+ *
454
+ */
455
+ static VALUE ft_face_faces(VALUE self) {
456
+ FT_Face *face;
457
+ Data_Get_Struct(self, FT_Face, face);
458
+ return INT2FIX((int) (*face)->num_faces);
459
+ }
460
+
461
+ /*
462
+ * Return the index of an FT2::Face object in its font file.
463
+ *
464
+ * Note:
465
+ * This is almost always zero.
466
+ *
467
+ * Aliases:
468
+ * FT2::Face#face_index
469
+ *
470
+ * Examples:
471
+ * index = face.index
472
+ *
473
+ */
474
+ static VALUE ft_face_index(VALUE self) {
475
+ FT_Face *face;
476
+ Data_Get_Struct(self, FT_Face, face);
477
+ return INT2FIX((int) (*face)->face_index);
478
+ }
479
+
480
+ /*
481
+ * Return the face flags of an FT2::Face object.
482
+ *
483
+ * You can binary OR this with any of the following values to obtain the
484
+ * value of that flag (note that this is returned as an Integer and not
485
+ * as a boolean value; eg non-zero for true and zero for false).
486
+ *
487
+ * Face Flags:
488
+ * FT2::Face::SCALABLE
489
+ * FT2::Face::FIXED_SIZES
490
+ * FT2::Face::FIXED_WIDTH
491
+ * FT2::Face::FIXED_HORIZONTAL
492
+ * FT2::Face::FIXED_VERTICAL
493
+ * FT2::Face::SFNT
494
+ * FT2::Face::KERNING
495
+ * FT2::Face::MULTIPLE_MASTERS
496
+ * FT2::Face::GLYPH_NAMES
497
+ * FT2::Face::EXTERNAL_STREAM
498
+ * FT2::Face::FAST_GLYPHS
499
+ *
500
+ * Alternatively, if you're only checking one flag, it's slightly faster
501
+ * (and arguably more concise), to use the following flag methods, which
502
+ * DO return true or false.
503
+ *
504
+ * Individual Flag Methods:
505
+ * FT2::Face#scalable?
506
+ * FT2::Face#fixed_sizes?
507
+ * FT2::Face#fixed_width?
508
+ * FT2::Face#horizontal?
509
+ * FT2::Face#vertical?
510
+ * FT2::Face#sfnt?
511
+ * FT2::Face#kerning?
512
+ * FT2::Face#external_stream?
513
+ * FT2::Face#fast_glyphs?
514
+ *
515
+ * Aliases:
516
+ * FT2::Face#face_flags
517
+ *
518
+ * Examples:
519
+ * if (face.flags & (FT2::Face::FAST_GLYPHS | FT2::Face::KERNING) != 0)
520
+ * puts 'face contains fast glyphs and kerning information'
521
+ * end
522
+ *
523
+ */
524
+ static VALUE ft_face_flags(VALUE self) {
525
+ FT_Face *face;
526
+ Data_Get_Struct(self, FT_Face, face);
527
+ return INT2FIX((int) (*face)->face_flags);
528
+ }
529
+
530
+ /*
531
+ * Is this FT2::Face scalable?
532
+ *
533
+ * Examples:
534
+ * puts "is scalable" if face.scalable?
535
+ *
536
+ */
537
+ static VALUE ft_face_flag_scalable(VALUE self) {
538
+ FT_Face *face;
539
+ Data_Get_Struct(self, FT_Face, face);
540
+ return ((*face)->face_flags & FT_FACE_FLAG_SCALABLE) ? Qtrue : Qfalse;
541
+ }
542
+
543
+ /*
544
+ * Does this FT2::Face contain bitmap strikes for some pixel sizes?
545
+ *
546
+ * Examples:
547
+ * puts "contains fixed sized glyphs" if face.fixed_sizes?
548
+ *
549
+ */
550
+ static VALUE ft_face_flag_fixed_sizes(VALUE self) {
551
+ FT_Face *face;
552
+ Data_Get_Struct(self, FT_Face, face);
553
+ return ((*face)->face_flags & FT_FACE_FLAG_FIXED_SIZES) ? Qtrue : Qfalse;
554
+ }
555
+
556
+ /*
557
+ * Does this FT2::Face contain fixed with characters?
558
+ *
559
+ * Examples:
560
+ * puts "contains fixed width characters" if face.fixed_width?
561
+ *
562
+ */
563
+ static VALUE ft_face_flag_fixed_width(VALUE self) {
564
+ FT_Face *face;
565
+ Data_Get_Struct(self, FT_Face, face);
566
+ return ((*face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH) ? Qtrue : Qfalse;
567
+ }
568
+
569
+ /*
570
+ * Does this FT2::Face contain horizontal glyph metrics?
571
+ *
572
+ * Note:
573
+ * This flag is true for virtually all fonts.
574
+ *
575
+ * Examples:
576
+ * puts "contains horizontal glyph metrics" if face.horizontal?
577
+ *
578
+ */
579
+ static VALUE ft_face_flag_horizontal(VALUE self) {
580
+ FT_Face *face;
581
+ Data_Get_Struct(self, FT_Face, face);
582
+ return ((*face)->face_flags & FT_FACE_FLAG_HORIZONTAL) ? Qtrue : Qfalse;
583
+ }
584
+
585
+ /*
586
+ * Does this FT2::Face contain vertical glyph metrics?
587
+ *
588
+ * Note:
589
+ * If this flag is not set, the glyph loader will synthesize vertical
590
+ * metrics itself.
591
+ *
592
+ * Examples:
593
+ * puts "contains vertical glyph metrics" if face.vertical?
594
+ *
595
+ */
596
+ static VALUE ft_face_flag_vertical(VALUE self) {
597
+ FT_Face *face;
598
+ Data_Get_Struct(self, FT_Face, face);
599
+ return ((*face)->face_flags & FT_FACE_FLAG_VERTICAL) ? Qtrue : Qfalse;
600
+ }
601
+
602
+ /*
603
+ * Is this FT2::Face stored in the 'sfnt' storage format?
604
+ *
605
+ * Note:
606
+ * This currently means the file was either TrueType or OpenType.
607
+ *
608
+ * Examples:
609
+ * puts "sfnt format font" if face.sfnt?
610
+ *
611
+ */
612
+ static VALUE ft_face_flag_sfnt(VALUE self) {
613
+ FT_Face *face;
614
+ Data_Get_Struct(self, FT_Face, face);
615
+ return ((*face)->face_flags & FT_FACE_FLAG_SFNT) ? Qtrue : Qfalse;
616
+ }
617
+
618
+ /*
619
+ * Does this FT2::Face contain kerning information?
620
+ *
621
+ * Examples:
622
+ * puts "face contains kerning information" if face.kerning?
623
+ *
624
+ */
625
+ static VALUE ft_face_flag_kerning(VALUE self) {
626
+ FT_Face *face;
627
+ Data_Get_Struct(self, FT_Face, face);
628
+ return ((*face)->face_flags & FT_FACE_FLAG_KERNING) ? Qtrue : Qfalse;
629
+ }
630
+
631
+ /*
632
+ * Was this FT2::Face loaded from an external stream?
633
+ *
634
+ * Examples:
635
+ * puts "face loaded from external stream" if face.external_stream?
636
+ *
637
+ */
638
+ static VALUE ft_face_flag_external_stream(VALUE self) {
639
+ FT_Face *face;
640
+ Data_Get_Struct(self, FT_Face, face);
641
+ return ((*face)->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM) ? Qtrue : Qfalse;
642
+ }
643
+
644
+ /*
645
+ * Does this FT2::Face contain fast glyphs?
646
+ *
647
+ * Note:
648
+ * This flag is usually set for fixed-size formats like FNT.
649
+ *
650
+ * Examples:
651
+ * puts "face contains fast glyphs" if face.fast_glyphs?
652
+ *
653
+ */
654
+ static VALUE ft_face_flag_fast_glyphs(VALUE self) {
655
+ FT_Face *face;
656
+ Data_Get_Struct(self, FT_Face, face);
657
+ return ((*face)->face_flags & FT_FACE_FLAG_FAST_GLYPHS) ? Qtrue : Qfalse;
658
+ }
659
+
660
+ /*
661
+ * Return the style flags of an FT2::Face object.
662
+ *
663
+ * You can binary OR this with any of the following values to obtain the
664
+ * value of that style flag (note that this is returned as an Integer
665
+ * and not as a boolean value; eg non-zero for true and zero for false).
666
+ *
667
+ * Style Flags:
668
+ * FT2::Face::BOLD
669
+ * FT2::Face::ITALIC
670
+ *
671
+ * Alternatively, if you're only checking one style flag, it's slightly
672
+ * faster (and arguably more concise), to use the following style flag
673
+ * methods, which DO return true or false.
674
+ *
675
+ * Individual Style Flag Methods:
676
+ * FT2::Face#bold?
677
+ * FT2::Face#italic?
678
+ *
679
+ * Examples:
680
+ * style = face.style_flags
681
+ *
682
+ */
683
+ static VALUE ft_face_style_flags(VALUE self) {
684
+ FT_Face *face;
685
+ Data_Get_Struct(self, FT_Face, face);
686
+ return INT2FIX((int) (*face)->style_flags);
687
+ }
688
+
689
+ /*
690
+ * Is this a bold FT2::Face?
691
+ *
692
+ * Examples:
693
+ * puts "bold face" if face.bold?
694
+ *
695
+ */
696
+ static VALUE ft_face_flag_bold(VALUE self) {
697
+ FT_Face *face;
698
+ Data_Get_Struct(self, FT_Face, face);
699
+ return ((*face)->style_flags & FT_STYLE_FLAG_BOLD) ? Qtrue : Qfalse;
700
+ }
701
+
702
+ /*
703
+ * Is this an italic FT2::Face?
704
+ *
705
+ * Examples:
706
+ * puts "italic face" if face.italic?
707
+ *
708
+ */
709
+ static VALUE ft_face_flag_italic(VALUE self) {
710
+ FT_Face *face;
711
+ Data_Get_Struct(self, FT_Face, face);
712
+ return ((*face)->style_flags & FT_STYLE_FLAG_ITALIC) ? Qtrue : Qfalse;
713
+ }
714
+
715
+ /*
716
+ * Return the number of glyphs in an FT2::Face object.
717
+ *
718
+ * Aliases:
719
+ * FT2::Face#num_glyphs
720
+ *
721
+ * Examples:
722
+ * count = face.glyphs
723
+ * puts "face has #{count.to_str} glyphs"
724
+ *
725
+ */
726
+ static VALUE ft_face_glyphs(VALUE self) {
727
+ FT_Face *face;
728
+ Data_Get_Struct(self, FT_Face, face);
729
+ return INT2FIX((int) (*face)->num_glyphs);
730
+ }
731
+
732
+ /*
733
+ * Return the family name of an FT2::Face object.
734
+ *
735
+ * Description:
736
+ * This is an ASCII string, usually in English, which describes the
737
+ * FT2::Face object's family (eg "Times New Roman" or "Geneva"). Some
738
+ * formats (eg Truetype and OpenType) provide localized and Unicode
739
+ * versions of this string, which are accessable via the format specific
740
+ * interfaces.
741
+ *
742
+ * Examples:
743
+ * puts 'family: ' << face.family
744
+ *
745
+ */
746
+ static VALUE ft_face_family(VALUE self) {
747
+ FT_Face *face;
748
+ Data_Get_Struct(self, FT_Face, face);
749
+ return rb_str_new2((*face)->family_name);
750
+ }
751
+
752
+ /*
753
+ * Return the style name of an FT2::Face object.
754
+ *
755
+ * Description:
756
+ * This is an ASCII string, usually in English, which describes the
757
+ * FT2::Face object's style (eg "Bold", "Italic", "Condensed", etc).
758
+ * This field is optional and may be set to nil.
759
+ *
760
+ * Examples:
761
+ * puts 'style: ' << face.style if face.style
762
+ *
763
+ */
764
+ static VALUE ft_face_style(VALUE self) {
765
+ FT_Face *face;
766
+ Data_Get_Struct(self, FT_Face, face);
767
+ if (!(*face)->style_name)
768
+ return Qnil;
769
+ return rb_str_new2((*face)->style_name);
770
+ }
771
+
772
+ /*
773
+ * Return the number of fixed sizes in an FT2::Face object.
774
+ *
775
+ * Note:
776
+ * This should be set to 0 for scalable fonts, unless the FT2::Face
777
+ * object contains a complete set of glyphs for the specified size.
778
+ *
779
+ * Aliases:
780
+ * FT2::Face#num_fixed_sizes
781
+ *
782
+ * Examples:
783
+ * puts 'fized sizes count: ' << face.fixed_sizes
784
+ *
785
+ */
786
+ static VALUE ft_face_fixed_sizes(VALUE self) {
787
+ FT_Face *face;
788
+ Data_Get_Struct(self, FT_Face, face);
789
+ return INT2FIX((int) (*face)->num_fixed_sizes);
790
+ }
791
+
792
+ /*
793
+ * Return an array of sizes in an FT2::Face object.
794
+ *
795
+ * Note:
796
+ * This method does not currently work..
797
+ *
798
+ * Examples:
799
+ * face.available_sizesdflksjaflksdjf FIXME
800
+ *
801
+ */
802
+ static VALUE ft_face_available_sizes(VALUE self) {
803
+ FT_Face *face;
804
+ Data_Get_Struct(self, FT_Face, face);
805
+ /* FIXME!! */
806
+ return INT2FIX((int) (*face)->available_sizes);
807
+ }
808
+
809
+ /*
810
+ * Return the number of charmaps in an FT2::Face object.
811
+ *
812
+ * Examples:
813
+ * puts 'number of charmaps: ' << face.num_charmaps
814
+ *
815
+ */
816
+ static VALUE ft_face_num_charmaps(VALUE self) {
817
+ FT_Face *face;
818
+ Data_Get_Struct(self, FT_Face, face);
819
+ return INT2FIX((int) (*face)->num_charmaps);
820
+ }
821
+
822
+ /*
823
+ * Return an array of charmaps in an FT2::Face object.
824
+ *
825
+ * Note:
826
+ * This method may not work correctly at the moment (FIXME).
827
+ *
828
+ * Examples:
829
+ * face.charmaps.each { |map| puts map.to_str }
830
+ *
831
+ */
832
+ static VALUE ft_face_charmaps(VALUE self) {
833
+ FT_Face *face;
834
+ VALUE ary;
835
+ int i;
836
+ Data_Get_Struct(self, FT_Face, face);
837
+
838
+ /* FIXME */
839
+ rb_bug("not implemented yet");
840
+ ary = rb_ary_new();
841
+ for (i = 0; i < (*face)->num_charmaps; i++)
842
+ rb_ary_push(ary, INT2FIX(i));
843
+
844
+ return ary;
845
+ }
846
+
847
+ /*
848
+ * Return the bounding box of an FT2::Face object.
849
+ *
850
+ * Note:
851
+ * This method is not currently implemented (FIXME).
852
+ *
853
+ * Examples:
854
+ * FIXME
855
+ *
856
+ */
857
+ static VALUE ft_face_bbox(VALUE self) {
858
+ UNUSED(self);
859
+ /* FIXME */
860
+ rb_bug("not implemented yet");
861
+ return Qnil;
862
+ }
863
+
864
+ /*
865
+ * Return the number of font units per EM for this FT2::Face object.
866
+ *
867
+ * Description:
868
+ * This value is typically 2048 for TrueType fonts, 1000 for Type1
869
+ * fonts, and should be set to the (unrealistic) value 1 for
870
+ * fixed-size fonts.
871
+ *
872
+ * Aliases:
873
+ * FT2::Face#units_per_EM
874
+ *
875
+ * Examples:
876
+ * em = face.units_per_em
877
+ *
878
+ */
879
+ static VALUE ft_face_units_per_em(VALUE self) {
880
+ FT_Face *face;
881
+ Data_Get_Struct(self, FT_Face, face);
882
+ return INT2FIX((int) (*face)->units_per_EM);
883
+ }
884
+
885
+ /*
886
+ * Return the ascender for this FT2::Face object.
887
+ *
888
+ * Description:
889
+ * An FT2::Face object's ascender is the vertical distance, in font
890
+ * units, from the baseline to the topmost point of any glyph in the
891
+ * face.
892
+ *
893
+ * Examples:
894
+ * asc = face.ascender
895
+ *
896
+ */
897
+ static VALUE ft_face_ascender(VALUE self) {
898
+ FT_Face *face;
899
+ Data_Get_Struct(self, FT_Face, face);
900
+ return INT2FIX((int) (*face)->ascender);
901
+ }
902
+
903
+ /*
904
+ * Return the descender for this FT2::Face object.
905
+ *
906
+ * Description:
907
+ * An FT2::Face object's descender is the vertical distance, in font
908
+ * units, from the baseline to the bottommost point of any glyph in
909
+ * the face.
910
+ *
911
+ * Examples:
912
+ * asc = face.descender
913
+ *
914
+ */
915
+ static VALUE ft_face_descender(VALUE self) {
916
+ FT_Face *face;
917
+ Data_Get_Struct(self, FT_Face, face);
918
+ return INT2FIX((int) (*face)->descender);
919
+ }
920
+
921
+ /*
922
+ * Return the height of this FT2::Face object.
923
+ *
924
+ * Description:
925
+ * An FT2::Face object's height is the vertical distance, in font
926
+ * units, from the baseline of one line to the baseline of the next.
927
+ * The value can be computed as 'ascender + descender + line_gap',
928
+ * where 'line_gap' is also called 'external leading'.
929
+ *
930
+ * Examples:
931
+ * h = face.height
932
+ *
933
+ */
934
+ static VALUE ft_face_height(VALUE self) {
935
+ FT_Face *face;
936
+ Data_Get_Struct(self, FT_Face, face);
937
+ return INT2FIX((int) (*face)->height);
938
+ }
939
+
940
+ /*
941
+ * Return the maximal advance width of this FT2::Face object.
942
+ *
943
+ * Description:
944
+ * The maximal advance width, in font units, for all glyphs in this
945
+ * FT2::Face object. This can be used to make word-wrapping
946
+ * computations faster. Only relevant for scalable formats.
947
+ *
948
+ * Examples:
949
+ * maw = face.max_advance_width
950
+ *
951
+ */
952
+ static VALUE ft_face_max_advance_width(VALUE self) {
953
+ FT_Face *face;
954
+ Data_Get_Struct(self, FT_Face, face);
955
+ return INT2FIX((int) (*face)->max_advance_width);
956
+ }
957
+
958
+ /*
959
+ * Return the maximal advance height of this FT2::Face object.
960
+ *
961
+ * Description:
962
+ * The maximal advance height, in font units, for all glyphs in this
963
+ * FT2::Face object. This can be used to make word-wrapping
964
+ * computations faster. Only relevant for scalable formats.
965
+ *
966
+ * Examples:
967
+ * mah = face.max_advance_height
968
+ *
969
+ */
970
+ static VALUE ft_face_max_advance_height(VALUE self) {
971
+ FT_Face *face;
972
+ Data_Get_Struct(self, FT_Face, face);
973
+ return INT2FIX((int) (*face)->max_advance_height);
974
+ }
975
+
976
+ /*
977
+ * Return the underline position of this FT2::Face object.
978
+ *
979
+ * Description:
980
+ * The position, in font units, of the underline line for this face.
981
+ * It's the center of the underlining stem. Only relevant for scalable
982
+ * formats.
983
+ *
984
+ * Examples:
985
+ * uh = face.underline_position
986
+ *
987
+ */
988
+ static VALUE ft_face_underline_position(VALUE self) {
989
+ FT_Face *face;
990
+ Data_Get_Struct(self, FT_Face, face);
991
+ return INT2FIX((int) (*face)->underline_position);
992
+ }
993
+
994
+ /*
995
+ * Return the underline thickness of this FT2::Face object.
996
+ *
997
+ * Description:
998
+ * The thickness, in font units, of the underline for this face. Only
999
+ * relevant for scalable formats.
1000
+ *
1001
+ * Examples:
1002
+ * ut = face.underline_thickness
1003
+ *
1004
+ */
1005
+ static VALUE ft_face_underline_thickness(VALUE self) {
1006
+ FT_Face *face;
1007
+ Data_Get_Struct(self, FT_Face, face);
1008
+ return INT2FIX((int) (*face)->underline_thickness);
1009
+ }
1010
+ /*
1011
+ * Return the glyph slot associated with this FT2::Face object.
1012
+ *
1013
+ * Description:
1014
+ * The face's associated glyph slot(s) (a FT2::GlyphSlot). This object
1015
+ * is created automatically with a new FT2::Face object. However,
1016
+ * certain kinds of applications (mainly tools like converters) can
1017
+ * need more than one slot to ease their task.
1018
+ *
1019
+ * Examples:
1020
+ * glyph = face.glyph
1021
+ *
1022
+ */
1023
+ static VALUE ft_face_glyph(VALUE self) {
1024
+ FT_Face *face;
1025
+ Data_Get_Struct(self, FT_Face, face);
1026
+
1027
+ if ((*face)->glyph)
1028
+ return Data_Wrap_Struct(cGlyphSlot, 0, dont_free, (*face)->glyph);
1029
+ else
1030
+ return Qnil;
1031
+ }
1032
+
1033
+ /*
1034
+ * Return the current active size of this FT2::Face object.
1035
+ *
1036
+ * Examples:
1037
+ * size = face.size
1038
+ *
1039
+ */
1040
+ static VALUE ft_face_size(VALUE self) {
1041
+ FT_Face *face;
1042
+ Data_Get_Struct(self, FT_Face, face);
1043
+
1044
+ if ((*face)->size)
1045
+ return Data_Wrap_Struct(cSize, 0, dont_free, (*face)->size);
1046
+ else
1047
+ return Qnil;
1048
+ }
1049
+
1050
+ /*
1051
+ * Return the current active FT2::CharMap of this FT2::Face object.
1052
+ *
1053
+ * Examples:
1054
+ * size = face.size
1055
+ *
1056
+ */
1057
+ static VALUE ft_face_charmap(VALUE self) {
1058
+ FT_Face *face;
1059
+ Data_Get_Struct(self, FT_Face, face);
1060
+
1061
+ if ((*face)->charmap)
1062
+ return Data_Wrap_Struct(cCharMap, 0, dont_free, (*face)->charmap);
1063
+ else
1064
+ return Qnil;
1065
+ }
1066
+
1067
+ /*
1068
+ * Attach a font file to this FT2::Face object.
1069
+ *
1070
+ * Description:
1071
+ * This is usually to read additional information for a single face
1072
+ * object. For example, it is used to read the AFM files that come
1073
+ * with Type 1 fonts in order to add kerning data and other metrics.
1074
+ * Throws an exception if the font file could not be loaded.
1075
+ * FreeType2 also supports loading from an input stream, but this
1076
+ * feature is not implemented in FT2-Ruby.
1077
+ *
1078
+ * Examples:
1079
+ * path = 'fonts'yudit.ttf'
1080
+ * begin
1081
+ * face.attach path # attach file "fonts/yudit.ttf"
1082
+ * rescue Exception
1083
+ * $stderr.puts "Couldn't open font file \"#{path}\": " << $!
1084
+ * end
1085
+ *
1086
+ */
1087
+ static VALUE ft_face_attach(VALUE self, VALUE path) {
1088
+ FT_Face *face;
1089
+ FT_Error err;
1090
+ Data_Get_Struct(self, FT_Face, face);
1091
+ if ((err = FT_Attach_File(*face, RSTRING(path)->ptr)) != FT_Err_Ok)
1092
+ handle_error(err);
1093
+ return self;
1094
+ }
1095
+
1096
+ /*
1097
+ * Set the character dimensions of this FT2::Face object.
1098
+ *
1099
+ * Description:
1100
+ * Sets the character dimensions of a FT2::Face object. The
1101
+ * `char_width' and `char_height' values are used for the width and
1102
+ * height, respectively, expressed in 26.6 fractional points.
1103
+ *
1104
+ * If the horizontal or vertical resolution values are zero, a default
1105
+ * value of 72dpi is used. Similarly, if one of the character
1106
+ * dimensions is zero, its value is set equal to the other.
1107
+ *
1108
+ * When dealing with fixed-size faces (i.e., non-scalable formats),
1109
+ * use the function FT2::Face#set_pixel_sizes .
1110
+ *
1111
+ * Examples:
1112
+ * face.set_char_size char_width, char_height, horiz_res, vert_res
1113
+ *
1114
+ */
1115
+ static VALUE ft_face_set_char_size(VALUE self, VALUE c_w, VALUE c_h, VALUE h_r, VALUE v_r) {
1116
+ FT_Face *face;
1117
+ FT_Error err;
1118
+ Data_Get_Struct(self, FT_Face, face);
1119
+ err = FT_Set_Char_Size(*face, NUM2DBL(c_w), NUM2DBL(c_h), NUM2INT(h_r), NUM2INT(v_r));
1120
+ if (err != FT_Err_Ok)
1121
+ handle_error(err);
1122
+ return self;
1123
+ }
1124
+
1125
+ /*
1126
+ * Set the character dimensions of this FT2::Face object.
1127
+ *
1128
+ * Description:
1129
+ * Sets the character dimensions of a FT2::Face object. The width and
1130
+ * height are expressed in integer pixels.
1131
+ *
1132
+ * If one of the character dimensions is zero, its value is set equal
1133
+ * to the other.
1134
+ *
1135
+ * The values of `pixel_width' and `pixel_height' correspond to the
1136
+ * pixel values of the typographic character size, which are NOT
1137
+ * necessarily the same as the dimensions of the glyph `bitmap cells'.
1138
+ *
1139
+ * The `character size' is really the size of an abstract square
1140
+ * called the `EM', used to design the font. However, depending on the
1141
+ * font design, glyphs will be smaller or greater than the EM.
1142
+ *
1143
+ * This means that setting the pixel size to, say, 8x8 doesn't
1144
+ * guarantee in any way that you will get glyph bitmaps that all fit
1145
+ * within an 8x8 cell (sometimes even far from it).
1146
+ *
1147
+ * Examples:
1148
+ * face.set_pixel_sizes pixel_width, pixel_height
1149
+ *
1150
+ */
1151
+ static VALUE ft_face_set_pixel_sizes(VALUE self, VALUE pixel_w, VALUE pixel_h) {
1152
+ FT_Face *face;
1153
+ FT_Error err;
1154
+ Data_Get_Struct(self, FT_Face, face);
1155
+ err = FT_Set_Pixel_Sizes(*face, NUM2INT(pixel_w), NUM2INT(pixel_h));
1156
+ if (err != FT_Err_Ok)
1157
+ handle_error(err);
1158
+ return self;
1159
+ }
1160
+
1161
+ /*
1162
+ * Set the pre-render transoformation matrix and vector of a FT2::Face object.
1163
+ *
1164
+ * Description:
1165
+ * Used to set the transformation that is applied to glyph images just
1166
+ * before they are converted to bitmaps in a FT2::GlyphSlot when
1167
+ * FT2::GlyphSlot#render is called.
1168
+ *
1169
+ * matrix: The transformation's 2x2 matrix. Use nil for the identity
1170
+ * matrix.
1171
+ * delta: The translation vector. Use nil for the null vector.
1172
+ *
1173
+ * Note:
1174
+ * The transformation is only applied to scalable image formats after
1175
+ * the glyph has been loaded. It means that hinting is unaltered by
1176
+ * the transformation and is performed on the character size given in
1177
+ * the last call to FT2::Face#set_char_sizes or
1178
+ * FT2::Face#set_pixel_sizes.
1179
+ *
1180
+ * Examples:
1181
+ * matrix = [[0, 1],
1182
+ * [0, 1]]
1183
+ * vector = nil
1184
+ *
1185
+ * face.set_transform matrix, vector
1186
+ *
1187
+ */
1188
+ static VALUE ft_face_set_transform(VALUE self, VALUE matrix, VALUE delta) {
1189
+ FT_Face *face;
1190
+ FT_Matrix m;
1191
+ FT_Vector v;
1192
+
1193
+ Data_Get_Struct(self, FT_Face, face);
1194
+
1195
+ if (matrix != Qnil) {
1196
+ /* FIXME: do I have these reversed? */
1197
+ m.xx = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix, 0), 0)));
1198
+ m.xy = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix, 1), 0)));
1199
+ m.yx = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix, 0), 1)));
1200
+ m.yy = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix, 1), 1)));
1201
+ }
1202
+
1203
+ if (delta != Qnil) {
1204
+ v.x = NUM2INT(rb_ary_entry(delta, 0));
1205
+ v.y = NUM2INT(rb_ary_entry(delta, 1));
1206
+ }
1207
+
1208
+ if (matrix != Qnil && delta != Qnil)
1209
+ FT_Set_Transform(*face, &m, &v);
1210
+ else if (matrix == Qnil && delta != Qnil)
1211
+ FT_Set_Transform(*face, NULL, &v);
1212
+ else if (matrix != Qnil && delta == Qnil)
1213
+ FT_Set_Transform(*face, &m, NULL);
1214
+ else
1215
+ FT_Set_Transform(*face, NULL, NULL);
1216
+
1217
+ return self;
1218
+ }
1219
+
1220
+ /*
1221
+ * Load a glyph at a given size into a glyph slot of a FT2::Face object.
1222
+ *
1223
+ * Description:
1224
+ * Load a glyph at a given size into a glyph slot of a FT2::Face
1225
+ * object.
1226
+ *
1227
+ * glyph_index: The index of the glyph in the font file.
1228
+ * load_flags: A flag indicating what to load for this glyph. The
1229
+ * FT2::Load::XXXX constants can be used to control the
1230
+ * glyph loading process (e.g., whether the outline should
1231
+ * be scaled, whether to load bitmaps or not, whether to
1232
+ * hint the outline, etc).
1233
+ *
1234
+ * Note:
1235
+ * If the glyph image is not a bitmap, and if the bit flag
1236
+ * FT2::Load::IGNORE_TRANSFORM is unset, the glyph image will be
1237
+ * transformed with the information passed to a previous call to
1238
+ * FT2::Face#set_transform
1239
+ *
1240
+ * Note that this also transforms the `face.glyph.advance' field, but
1241
+ * not the values in `face.glyph.metrics'.
1242
+ *
1243
+ * Load Flags:
1244
+ * FT2::Load::DEFAULT
1245
+ * FT2::Load::RENDER
1246
+ * FT2::Load::MONOCHROME
1247
+ * FT2::Load::LINEAR_DESIGN
1248
+ * FT2::Load::NO_SCALE
1249
+ * FT2::Load::NO_HINTING
1250
+ * FT2::Load::NO_BITMAP
1251
+ * FT2::Load::CROP_BITMAP
1252
+ * FT2::Load::VERTICAL_LAYOUT
1253
+ * FT2::Load::IGNORE_TRANSFORM
1254
+ * FT2::Load::IGNORE_GLOBAL_ADVANCE_WIDTH
1255
+ * FT2::Load::FORCE_AUTOHINT
1256
+ * FT2::Load::NO_RECURSE
1257
+ * FT2::Load::PEDANTIC
1258
+ *
1259
+ * Examples:
1260
+ * face.load_glyph 5, FT2::Load::DEFAULT
1261
+ *
1262
+ */
1263
+ static VALUE ft_face_load_glyph(VALUE self, VALUE glyph_index, VALUE flags) {
1264
+ FT_Face *face;
1265
+ FT_Error err;
1266
+
1267
+ Data_Get_Struct(self, FT_Face, face);
1268
+ if (flags == Qnil)
1269
+ flags = INT2FIX(FT_LOAD_DEFAULT);
1270
+
1271
+ err = FT_Load_Glyph(*face, NUM2INT(glyph_index), NUM2INT(flags));
1272
+ if (err != FT_Err_Ok)
1273
+ handle_error(err);
1274
+
1275
+ return self;
1276
+ }
1277
+
1278
+ /*
1279
+ * Load a glyph at a given size into a glyph slot of a FT2::Face object.
1280
+ *
1281
+ * Description:
1282
+ * Load a glyph at a given size into a glyph slot of a FT2::Face
1283
+ * object according to its character code.
1284
+ *
1285
+ * char_code: The glyph's character code, according to the current
1286
+ * charmap used in the FT2::Face object.
1287
+ * load_flags: A flag indicating what to load for this glyph. The
1288
+ * FT2::Load::XXXX constants can be used to control the
1289
+ * glyph loading process (e.g., whether the outline should
1290
+ * be scaled, whether to load bitmaps or not, whether to
1291
+ * hint the outline, etc).
1292
+ *
1293
+ * Note:
1294
+ * If the face has no current charmap, or if the character code is not
1295
+ * defined in the charmap, this function will return an error.
1296
+ *
1297
+ * If the glyph image is not a bitmap, and if the bit flag
1298
+ * FT2::Load::IGNORE_TRANSFORM is unset, the glyph image will be
1299
+ * transformed with the information passed to a previous call to
1300
+ * FT2::Face#set_transform
1301
+ *
1302
+ * Note that this also transforms the `face.glyph.advance' field, but
1303
+ * not the values in `face.glyph.metrics'.
1304
+ *
1305
+ * Load Flags:
1306
+ * FT2::Load::DEFAULT
1307
+ * FT2::Load::RENDER
1308
+ * FT2::Load::MONOCHROME
1309
+ * FT2::Load::LINEAR_DESIGN
1310
+ * FT2::Load::NO_SCALE
1311
+ * FT2::Load::NO_HINTING
1312
+ * FT2::Load::NO_BITMAP
1313
+ * FT2::Load::CROP_BITMAP
1314
+ * FT2::Load::VERTICAL_LAYOUT
1315
+ * FT2::Load::IGNORE_TRANSFORM
1316
+ * FT2::Load::IGNORE_GLOBAL_ADVANCE_WIDTH
1317
+ * FT2::Load::FORCE_AUTOHINT
1318
+ * FT2::Load::NO_RECURSE
1319
+ * FT2::Load::PEDANTIC
1320
+ *
1321
+ * Examples:
1322
+ * face.load_char 5, FT2::Load::DEFAULT
1323
+ *
1324
+ */
1325
+ static VALUE ft_face_load_char(VALUE self, VALUE char_code, VALUE flags) {
1326
+ FT_Face *face;
1327
+ FT_Error err;
1328
+ Data_Get_Struct(self, FT_Face, face);
1329
+ err = FT_Load_Char(*face, NUM2INT(char_code), NUM2INT(flags));
1330
+ if (err != FT_Err_Ok)
1331
+ handle_error(err);
1332
+ return self;
1333
+ }
1334
+
1335
+ /*
1336
+ * Get the glyph index of a character code.
1337
+ *
1338
+ * Note:
1339
+ * This function uses a charmap object in order to do the translation.
1340
+ *
1341
+ * FreeType computes its own glyph indices which are not necessarily
1342
+ * the same as used in the font in case the font is based on glyph
1343
+ * indices. Reason for this behaviour is to assure that index 0 is
1344
+ * never used, representing the missing glyph.
1345
+ *
1346
+ * A return value of 0 means `undefined character code'.
1347
+ *
1348
+ * Examples:
1349
+ * index = face.char_index 65
1350
+ * puts 'undefined character code' if index == 0
1351
+ *
1352
+ */
1353
+ static VALUE ft_face_char_index(VALUE self, VALUE char_code) {
1354
+ FT_Face *face;
1355
+ Data_Get_Struct(self, FT_Face, face);
1356
+ return INT2FIX(FT_Get_Char_Index(*face, NUM2INT(char_code)));
1357
+ }
1358
+
1359
+ /*
1360
+ * Get the glyph index of a given glyph name.
1361
+ *
1362
+ * Note:
1363
+ * This method uses driver specific objects to do the translation.
1364
+ *
1365
+ * A return value of 0 means `undefined character code'.
1366
+ *
1367
+ * Examples:
1368
+ * index = face.name_index glyph_name
1369
+ *
1370
+ */
1371
+ static VALUE ft_face_name_index(VALUE self, VALUE glyph_name) {
1372
+ FT_Face *face;
1373
+ Data_Get_Struct(self, FT_Face, face);
1374
+ return INT2FIX(FT_Get_Name_Index(*face, RSTRING(glyph_name)->ptr));
1375
+ }
1376
+
1377
+ /*
1378
+ * Get the kerning vector between two glyphs of a FT2::Face object.
1379
+ *
1380
+ * Description:
1381
+ * Get the kerning vector between two glyphs of a FT2::Face object.
1382
+ *
1383
+ * left_glyph: The index of the left glyph in the kern pair.
1384
+ * right_glyph: The index of the right glyph in the kern pair.
1385
+ * kern_mode: One of the FT2::KerningMode::XXXX constants. Determines
1386
+ * the scale/dimension of the returned kerning vector.
1387
+ *
1388
+ * Passing kern_mode == nil is the same as FT2::KerningMode::DEFAULT.
1389
+ *
1390
+ * Returns a kerning vector (actually a two-element array). This is in
1391
+ * font units for scalable formats, and in pixels for fixed-sizes
1392
+ * formats.
1393
+ *
1394
+ * Kerning Modes:
1395
+ * FT2::KerningMode::DEFAULT
1396
+ * FT2::KerningMode::UNFITTED
1397
+ * FT2::KerningMode::UNSCALED
1398
+ *
1399
+ * Examples:
1400
+ * left_glyph = 10
1401
+ * left_glyph = 11
1402
+ * k_v = face.kerning left_glyph, right_glyph, nil
1403
+ *
1404
+ * # another example, w/o default options
1405
+ * k_v = face.get_kerning 12, 13, FT2::KerningMode::UNFITTED
1406
+ *
1407
+ */
1408
+ static VALUE ft_face_kerning(VALUE self, VALUE left_glyph, VALUE right_glyph, VALUE kern_mode) {
1409
+ FT_Face *face;
1410
+ FT_Error err;
1411
+ FT_Vector v;
1412
+ VALUE ary;
1413
+
1414
+ Data_Get_Struct(self, FT_Face, face);
1415
+ ary = rb_ary_new();
1416
+
1417
+ if (kern_mode == Qnil)
1418
+ kern_mode = NUM2INT(ft_kerning_default);
1419
+
1420
+ err = FT_Get_Kerning(*face, NUM2INT(left_glyph), NUM2INT(right_glyph), NUM2INT(kern_mode), &v);
1421
+ if (err != FT_Err_Ok)
1422
+ handle_error(err);
1423
+
1424
+ rb_ary_push(ary, INT2FIX(v.x));
1425
+ rb_ary_push(ary, INT2FIX(v.y));
1426
+
1427
+ return ary;
1428
+ }
1429
+
1430
+ /*
1431
+ * Get the ASCII name of a glyph in a FT2::Face object.
1432
+ *
1433
+ * Note:
1434
+ * If the face doesn't provide glyph names or if the glyph index is
1435
+ * invalid, nil is returned. The glyph name is truncated if it is
1436
+ * longer than 1024 characters.
1437
+ *
1438
+ * Examples:
1439
+ * glyph_index = 45
1440
+ * glyph_name = face.glyph_name glyph_index
1441
+ *
1442
+ */
1443
+ static VALUE ft_face_glyph_name(VALUE self, VALUE glyph_index) {
1444
+ FT_Face *face;
1445
+ FT_Error err;
1446
+ char buf[1024];
1447
+ Data_Get_Struct(self, FT_Face, face);
1448
+ err = FT_Get_Glyph_Name(*face, NUM2INT(glyph_index), buf, sizeof(buf));
1449
+ if (err != FT_Err_Ok)
1450
+ handle_error(err);
1451
+
1452
+ return (buf && strlen(buf)) ? rb_str_new2(buf) : Qnil;
1453
+ }
1454
+
1455
+ /*
1456
+ * Get the ASCII Postscript name of a FT2::Face object.
1457
+ *
1458
+ * Note:
1459
+ * This should only work with Postscript and TrueType fonts. If the
1460
+ * PostScript name is un-avaialble, nil is returned.
1461
+ *
1462
+ * Examples:
1463
+ * ps_name = face.postscript_name
1464
+ * name = face.name
1465
+ *
1466
+ */
1467
+ static VALUE ft_face_ps_name(VALUE self) {
1468
+ FT_Face *face;
1469
+ const char *str;
1470
+ Data_Get_Struct(self, FT_Face, face);
1471
+
1472
+ if ((str = FT_Get_Postscript_Name(*face)) != NULL)
1473
+ return rb_str_new2(str);
1474
+ else
1475
+ return Qnil;
1476
+ }
1477
+
1478
+ /*
1479
+ * Select a FT2::Face object's charmap by its encoding tag.
1480
+ *
1481
+ * Encoding Tags:
1482
+ * FT2::Encoding::NONE
1483
+ * FT2::Encoding::SYMBOL
1484
+ * FT2::Encoding::UNICODE
1485
+ * FT2::Encoding::LATIN_1
1486
+ *
1487
+ * Examples:
1488
+ * face.select_charmap FT2::Encoding::UNICODE
1489
+ *
1490
+ */
1491
+ static VALUE ft_face_select_charmap(VALUE self, VALUE encoding) {
1492
+ FT_Face *face;
1493
+ FT_Error err;
1494
+ Data_Get_Struct(self, FT_Face, face);
1495
+ err = FT_Select_Charmap(*face, NUM2INT(encoding));
1496
+ if (err != FT_Err_Ok)
1497
+ handle_error(err);
1498
+ return self;
1499
+ }
1500
+
1501
+ /*
1502
+ * Select the FT2::Face object's charmap for character code to glyph index decoding.
1503
+ *
1504
+ * Examples:
1505
+ * charmap = face.charmaps[0]
1506
+ * face.set_charmap charmap
1507
+ *
1508
+ * charmap = face.charmaps[0]
1509
+ * face.charmap = charmap
1510
+ *
1511
+ */
1512
+ static VALUE ft_face_set_charmap(VALUE self, VALUE charmap) {
1513
+ FT_Face *face;
1514
+ FT_CharMap *cm;
1515
+ FT_Error err;
1516
+ Data_Get_Struct(self, FT_Face, face);
1517
+ Data_Get_Struct(charmap, FT_CharMap, cm);
1518
+ err = FT_Set_Charmap(*face, *cm);
1519
+ if (err != FT_Err_Ok)
1520
+ handle_error(err);
1521
+ return self;
1522
+ }
1523
+
1524
+ /*
1525
+ * Return the first character code of the selected charmap and corresponding glyph index of a FT2::Face object.
1526
+ *
1527
+ * Note:
1528
+ * Using this with FT2::Face#next_char will allow you to iterate
1529
+ * through the charmap => glyph index mapping for the selected
1530
+ * charmap.
1531
+ *
1532
+ * You should probably use the method FT2::Face#current_charmap
1533
+ * instead.
1534
+ *
1535
+ * Examples:
1536
+ * c_code, g_idx = face.first_char
1537
+ * while g_idx != 0
1538
+ * puts "#{c_code} => #{g_idx}"
1539
+ * c_code, g_idx = face.next_char
1540
+ * end
1541
+ *
1542
+ */
1543
+ static VALUE ft_face_first_char(VALUE self) {
1544
+ FT_Face *face;
1545
+ VALUE ary;
1546
+ FT_ULong char_code;
1547
+ FT_UInt glyph_index;
1548
+ Data_Get_Struct(self, FT_Face, face);
1549
+ ary = rb_ary_new();
1550
+
1551
+ char_code = FT_Get_First_Char(*face, &glyph_index);
1552
+ rb_ary_push(ary, UINT2NUM(char_code));
1553
+ rb_ary_push(ary, UINT2NUM(glyph_index));
1554
+
1555
+ return ary;
1556
+ }
1557
+
1558
+ /*
1559
+ * Return the next character code of the selected charmap and corresponding glyph index of a FT2::Face object.
1560
+ *
1561
+ * Note:
1562
+ * Using this with FT2::Face#first_char will allow you to iterate
1563
+ * through the charmap => glyph index mapping for the selected
1564
+ * charmap. Returns 0 if the charmap is empty, or if there are no
1565
+ * more codes in the charmap.
1566
+ *
1567
+ * You should probably use the method FT2::Face#current_charmap
1568
+ * instead.
1569
+ *
1570
+ * Examples:
1571
+ * c_code, g_idx = face.first_char
1572
+ * while g_idx != 0
1573
+ * puts "#{c_code} => #{g_idx}"
1574
+ * c_code, g_idx = face.next_char
1575
+ * end
1576
+ *
1577
+ */
1578
+ static VALUE ft_face_next_char(VALUE self, VALUE char_code) {
1579
+ FT_Face *face;
1580
+ VALUE ary;
1581
+ FT_ULong ret_char_code;
1582
+ FT_UInt glyph_index;
1583
+ Data_Get_Struct(self, FT_Face, face);
1584
+ ary = rb_ary_new();
1585
+
1586
+ ret_char_code = FT_Get_Next_Char(*face, char_code, &glyph_index);
1587
+ rb_ary_push(ary, UINT2NUM(ret_char_code));
1588
+ rb_ary_push(ary, UINT2NUM(glyph_index));
1589
+
1590
+ return ary;
1591
+ }
1592
+
1593
+ /*
1594
+ * Return the character code to glyph index map of the selected charmap of a FT2::Face object.
1595
+ *
1596
+ * Note:
1597
+ * Returns nil if the selected charmap is empty.
1598
+ *
1599
+ * Examples:
1600
+ * mapping = face.charmap
1601
+ *
1602
+ */
1603
+ static VALUE ft_face_current_charmap(VALUE self) {
1604
+ FT_Face *face;
1605
+ FT_ULong c_code;
1606
+ FT_UInt g_idx;
1607
+ VALUE rtn;
1608
+
1609
+ rtn = Qnil;
1610
+ Data_Get_Struct(self, FT_Face, face);
1611
+
1612
+ c_code = FT_Get_First_Char(*face, &g_idx);
1613
+ if (!g_idx || !c_code)
1614
+ return rtn;
1615
+
1616
+ rtn = rb_hash_new();
1617
+ while (c_code != 0) {
1618
+ rb_hash_aset(rtn, UINT2NUM(c_code), UINT2NUM(g_idx));
1619
+ c_code = FT_Get_Next_Char(*face, c_code, &g_idx);
1620
+ }
1621
+
1622
+ return rtn;
1623
+ }
1624
+
1625
+
1626
+ /*****************************/
1627
+ /* FT2::GlyphMetrics methods */
1628
+ /*****************************/
1629
+
1630
+ /*
1631
+ * Constructor for FT2::GlyphMetrics
1632
+ *
1633
+ * This method is currently empty. You should never call this method
1634
+ * directly unless you're instantiating a derived class (ie, you know
1635
+ * what you're doing).
1636
+ *
1637
+ */
1638
+ static VALUE ft_glyphmetrics_init(VALUE self) {
1639
+ return self;
1640
+ }
1641
+
1642
+ /*
1643
+ * Get the glyph's width.
1644
+ *
1645
+ * Note:
1646
+ * Values are expressed in 26.6 fractional pixel format or in font
1647
+ * units, depending on context.
1648
+ *
1649
+ * Aliases:
1650
+ * FT2::GlyphMetrics#w
1651
+ *
1652
+ * Examples:
1653
+ * w = slot.metrics.width
1654
+ * w = slot.metrics.w
1655
+ *
1656
+ */
1657
+ static VALUE ft_glyphmetrics_width(VALUE self) {
1658
+ FT_Glyph_Metrics *glyph;
1659
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1660
+ return INT2NUM(glyph->width);
1661
+ }
1662
+
1663
+ /*
1664
+ * Get the glyph's height.
1665
+ *
1666
+ * Note:
1667
+ * Values are expressed in 26.6 fractional pixel format or in font
1668
+ * units, depending on context.
1669
+ *
1670
+ * Aliases:
1671
+ * FT2::GlyphMetrics#h
1672
+ *
1673
+ * Examples:
1674
+ * h = slot.metrics.height
1675
+ * h = slot.metrics.h
1676
+ *
1677
+ */
1678
+ static VALUE ft_glyphmetrics_height(VALUE self) {
1679
+ FT_Glyph_Metrics *glyph;
1680
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1681
+ return INT2NUM(glyph->height);
1682
+ }
1683
+
1684
+ /*
1685
+ * Get the glyph's left side bearing in horizontal layouts.
1686
+ *
1687
+ * Note:
1688
+ * Values are expressed in 26.6 fractional pixel format or in font
1689
+ * units, depending on context.
1690
+ *
1691
+ * Aliases:
1692
+ * FT2::GlyphMetrics#horiBearingX
1693
+ * FT2::GlyphMetrics#h_bear_x
1694
+ * FT2::GlyphMetrics#hbx
1695
+ *
1696
+ * Examples:
1697
+ * hbx = slot.metrics.h_bearing_x
1698
+ * hbx = slot.metrics.horiBearingX
1699
+ * hbx = slot.metrics.h_bear_x
1700
+ * hbx = slot.metrics.hbx
1701
+ *
1702
+ */
1703
+ static VALUE ft_glyphmetrics_h_bear_x(VALUE self) {
1704
+ FT_Glyph_Metrics *glyph;
1705
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1706
+ return INT2NUM(glyph->horiBearingX);
1707
+ }
1708
+
1709
+ /*
1710
+ * Get the glyph's top side bearing in horizontal layouts.
1711
+ *
1712
+ * Note:
1713
+ * Values are expressed in 26.6 fractional pixel format or in font
1714
+ * units, depending on context.
1715
+ *
1716
+ * Aliases:
1717
+ * FT2::GlyphMetrics#horiBearingY
1718
+ * FT2::GlyphMetrics#h_bear_y
1719
+ * FT2::GlyphMetrics#hby
1720
+ *
1721
+ * Examples:
1722
+ * hby = slot.metrics.h_bearing_y
1723
+ * hby = slot.metrics.horiBearingY
1724
+ * hby = slot.metrics.h_bear_y
1725
+ * hby = slot.metrics.hby
1726
+ *
1727
+ */
1728
+ static VALUE ft_glyphmetrics_h_bear_y(VALUE self) {
1729
+ FT_Glyph_Metrics *glyph;
1730
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1731
+ return INT2NUM(glyph->horiBearingY);
1732
+ }
1733
+
1734
+ /*
1735
+ * Get the glyph's advance width for horizontal layouts.
1736
+ *
1737
+ * Note:
1738
+ * Values are expressed in 26.6 fractional pixel format or in font
1739
+ * units, depending on context.
1740
+ *
1741
+ * Aliases:
1742
+ * FT2::GlyphMetrics#horiAdvance
1743
+ * FT2::GlyphMetrics#ha
1744
+ *
1745
+ * Examples:
1746
+ * ha = slot.metrics.h_advance
1747
+ * ha = slot.metrics.horiAdvance
1748
+ * ha = slot.metrics.ha
1749
+ *
1750
+ */
1751
+ static VALUE ft_glyphmetrics_h_advance(VALUE self) {
1752
+ FT_Glyph_Metrics *glyph;
1753
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1754
+ return INT2NUM(glyph->horiAdvance);
1755
+ }
1756
+
1757
+ /*
1758
+ * Get the glyph's left side bearing in vertical layouts.
1759
+ *
1760
+ * Note:
1761
+ * Values are expressed in 26.6 fractional pixel format or in font
1762
+ * units, depending on context.
1763
+ *
1764
+ * Aliases:
1765
+ * FT2::GlyphMetrics#vertBearingX
1766
+ * FT2::GlyphMetrics#v_bear_x
1767
+ * FT2::GlyphMetrics#vbx
1768
+ *
1769
+ * Examples:
1770
+ * vbx = slot.metrics.v_bearing_x
1771
+ * vbx = slot.metrics.vertBearingX
1772
+ * vbx = slot.metrics.v_bear_x
1773
+ * vbx = slot.metrics.vbx
1774
+ *
1775
+ */
1776
+ static VALUE ft_glyphmetrics_v_bear_x(VALUE self) {
1777
+ FT_Glyph_Metrics *glyph;
1778
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1779
+ return INT2NUM(glyph->vertBearingX);
1780
+ }
1781
+
1782
+ /*
1783
+ * Get the glyph's top side bearing in vertical layouts.
1784
+ *
1785
+ * Note:
1786
+ * Values are expressed in 26.6 fractional pixel format or in font
1787
+ * units, depending on context.
1788
+ *
1789
+ * Aliases:
1790
+ * FT2::GlyphMetrics#vertBearingY
1791
+ * FT2::GlyphMetrics#v_bear_y
1792
+ * FT2::GlyphMetrics#vby
1793
+ *
1794
+ * Examples:
1795
+ * vby = slot.metrics.v_bearing_y
1796
+ * vby = slot.metrics.vertBearingY
1797
+ * vby = slot.metrics.v_bear_y
1798
+ * vby = slot.metrics.vby
1799
+ *
1800
+ */
1801
+ static VALUE ft_glyphmetrics_v_bear_y(VALUE self) {
1802
+ FT_Glyph_Metrics *glyph;
1803
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1804
+ return INT2NUM(glyph->vertBearingY);
1805
+ }
1806
+
1807
+ /*
1808
+ * Get the glyph's advance width for vertical layouts.
1809
+ *
1810
+ * Note:
1811
+ * Values are expressed in 26.6 fractional pixel format or in font
1812
+ * units, depending on context.
1813
+ *
1814
+ * Aliases:
1815
+ * FT2::GlyphMetrics#vertAdvance
1816
+ * FT2::GlyphMetrics#va
1817
+ *
1818
+ * Examples:
1819
+ * va = slot.metrics.v_advance
1820
+ * va = slot.metrics.vertAdvance
1821
+ * va = slot.metrics.va
1822
+ *
1823
+ */
1824
+ static VALUE ft_glyphmetrics_v_advance(VALUE self) {
1825
+ FT_Glyph_Metrics *glyph;
1826
+ Data_Get_Struct(self, FT_Glyph_Metrics, glyph);
1827
+ return INT2NUM(glyph->vertAdvance);
1828
+ }
1829
+
1830
+
1831
+ /**************************/
1832
+ /* FT2::GlyphSlot methods */
1833
+ /**************************/
1834
+
1835
+ /*
1836
+ * Constructor for FT2::GlyphSlot class.
1837
+ *
1838
+ * This method is currently empty. You should never call this method
1839
+ * directly unless you're instantiating a derived class (ie, you know
1840
+ * what you're doing).
1841
+ *
1842
+ */
1843
+ static VALUE ft_glyphslot_init(VALUE self) {
1844
+ return self;
1845
+ }
1846
+
1847
+ /*
1848
+ * Convert a FT2::GlyphSlot object to a bitmap.
1849
+ *
1850
+ * Description:
1851
+ * Converts a given FT2::GlyphSlot to a bitmap. It does so by
1852
+ * $inspecting the FT2::GlyphSlot format, finding the relevant
1853
+ * renderer, and invoking it.
1854
+ *
1855
+ * render_mode: This is the render mode used to render the glyph image
1856
+ * into a bitmap. See below for a list of possible
1857
+ * values. If render_mode is nil, then it defaults to
1858
+ * FT2::RenderMode::NORMAL.
1859
+ *
1860
+ * Aliases:
1861
+ * FT2::GlyphSlot#render_glyph
1862
+ *
1863
+ * Render Modes:
1864
+ * FT2::RenderMode::NORMAL
1865
+ * FT2::RenderMode::MONO
1866
+ *
1867
+ * Examples:
1868
+ * slot.render FT2::RenderMode::NORMAL
1869
+ *
1870
+ */
1871
+ static VALUE ft_glyphslot_render(VALUE self, VALUE render_mode) {
1872
+ FT_Error err;
1873
+ FT_GlyphSlot *glyph;
1874
+
1875
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1876
+ if (render_mode == Qnil)
1877
+ render_mode = INT2FIX(ft_render_mode_normal);
1878
+
1879
+ err = FT_Render_Glyph(*glyph, NUM2INT(render_mode));
1880
+ if (err != FT_Err_Ok)
1881
+ handle_error(err);
1882
+
1883
+ return self;
1884
+ }
1885
+
1886
+ static VALUE ft_glyphslot_glyph(VALUE self) {
1887
+ FT_Error err;
1888
+ FT_GlyphSlot *slot;
1889
+ FT_Glyph *glyph;
1890
+
1891
+ glyph = malloc(sizeof(FT_Glyph));
1892
+ Data_Get_Struct(self, FT_GlyphSlot, slot);
1893
+ err = FT_Get_Glyph(*slot, glyph);
1894
+ if (err != FT_Err_Ok) {
1895
+ free(glyph);
1896
+ handle_error(err);
1897
+ }
1898
+
1899
+ return Data_Wrap_Struct(cGlyph, 0, glyph_free, glyph);
1900
+ }
1901
+
1902
+ /*
1903
+ * Get the FT2::Library instance this FT2::GlyphSlot object belongs to.
1904
+ *
1905
+ * Examples:
1906
+ * lib = slot.library
1907
+ *
1908
+ */
1909
+ static VALUE ft_glyphslot_library(VALUE self) {
1910
+ FT_GlyphSlot *glyph;
1911
+ FT_Library *lib;
1912
+
1913
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1914
+ lib = malloc(sizeof(FT_Library));
1915
+ *lib = (*glyph)->library;
1916
+
1917
+ return Data_Wrap_Struct(cLibrary, 0, dont_free, lib);
1918
+ }
1919
+
1920
+ /*
1921
+ * Get the FT2::Face object this FT2::GlyphSlot object belongs to.
1922
+ *
1923
+ * Examples:
1924
+ * face = slot.face
1925
+ *
1926
+ */
1927
+ static VALUE ft_glyphslot_face(VALUE self) {
1928
+ FT_GlyphSlot *glyph;
1929
+ FT_Face *face;
1930
+
1931
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1932
+ face = malloc(sizeof(FT_Face));
1933
+ *face = (*glyph)->face;
1934
+
1935
+ /* do we really want to dont_free() cb here? */
1936
+ return Data_Wrap_Struct(cFace, 0, dont_free, face);
1937
+ }
1938
+
1939
+ /*
1940
+ * Get the next FT2::GlyphSlot object.
1941
+ *
1942
+ * Description:
1943
+ * In some cases (like some font tools), several FT2::GlyphSlot s per
1944
+ * FT2::Face object can be a good thing. As this is rare, the
1945
+ * FT2::GlyphSlot s are listed through a direct, single-linked list
1946
+ * using its `next' field.
1947
+ *
1948
+ * Examples:
1949
+ * next_slot = slot.next
1950
+ *
1951
+ */
1952
+ static VALUE ft_glyphslot_next(VALUE self) {
1953
+ FT_GlyphSlot *glyph;
1954
+ FT_GlyphSlot *next;
1955
+
1956
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1957
+ next = malloc(sizeof(FT_GlyphSlot));
1958
+ *next = (*glyph)->next;
1959
+
1960
+ /* do we really want to dont_free() cb here? */
1961
+ return Data_Wrap_Struct(cGlyphSlot, 0, dont_free, next);
1962
+ }
1963
+
1964
+ /*
1965
+ * Get the flags of a FT2::GlyphSlot.
1966
+ *
1967
+ * Examples:
1968
+ * flags = slot.flags
1969
+ *
1970
+ */
1971
+ static VALUE ft_glyphslot_flags(VALUE self) {
1972
+ FT_GlyphSlot *glyph;
1973
+
1974
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1975
+ return INT2NUM(0); //XXX: we don't use this, and it was causing a compiler error
1976
+ }
1977
+
1978
+ /*
1979
+ * Get the FT2::GlyphMetrics of a FT2::GlyphSlot object.
1980
+ *
1981
+ * Examples:
1982
+ * metrics = slot.metrics
1983
+ *
1984
+ */
1985
+ static VALUE ft_glyphslot_metrics(VALUE self) {
1986
+ FT_GlyphSlot *glyph;
1987
+ FT_Glyph_Metrics *metrics;
1988
+
1989
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
1990
+ metrics = malloc(sizeof(FT_Glyph_Metrics));
1991
+ *metrics = (*glyph)->metrics;
1992
+
1993
+ return Data_Wrap_Struct(cGlyphMetrics, 0, dont_free, metrics);
1994
+ }
1995
+
1996
+ /*
1997
+ * Get the linearly scaled horizontal advance width of a FT2::GlyphSlot object.
1998
+ *
1999
+ * Description:
2000
+ * For scalable formats only, this field holds the linearly scaled
2001
+ * horizontal advance width for the FT2:GlyphSlot (i.e. the scaled and
2002
+ * unhinted value of the hori advance). This can be important to
2003
+ * perform correct WYSIWYG layout.
2004
+ *
2005
+ * Note:
2006
+ * The return value is expressed by default in 16.16 pixels. However,
2007
+ * when the FT2::GlyphSlot is loaded with the FT2::Load::LINEAR_DESIGN
2008
+ * flag, this field contains simply the value of the advance in
2009
+ * original font units.
2010
+ *
2011
+ * Aliases:
2012
+ * FT2::GlyphSlot#linearHoriAdvance
2013
+ * FT2::GlyphSlot#h_adv
2014
+ * FT2::GlyphSlot#ha
2015
+ *
2016
+ * Examples:
2017
+ * h_adv = slot.h_advance
2018
+ *
2019
+ */
2020
+ static VALUE ft_glyphslot_h_advance(VALUE self) {
2021
+ FT_GlyphSlot *glyph;
2022
+
2023
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2024
+ return rb_float_new(FTFIX2DBL((*glyph)->linearHoriAdvance));
2025
+ }
2026
+
2027
+ /*
2028
+ * Get the linearly scaled vertical advance height of a FT2::GlyphSlot object.
2029
+ *
2030
+ * Description:
2031
+ * For scalable formats only, this field holds the linearly scaled
2032
+ * vertical advance height for the FT2:GlyphSlot (i.e. the scaled and
2033
+ * unhinted value of the hori advance). This can be important to
2034
+ * perform correct WYSIWYG layout.
2035
+ *
2036
+ * Note:
2037
+ * The return value is expressed by default in 16.16 pixels. However,
2038
+ * when the FT2::GlyphSlot is loaded with the FT2::Load::LINEAR_DESIGN
2039
+ * flag, this field contains simply the value of the advance in
2040
+ * original font units.
2041
+ *
2042
+ * Aliases:
2043
+ * FT2::GlyphSlot#linearVertAdvance
2044
+ * FT2::GlyphSlot#v_adv
2045
+ * FT2::GlyphSlot#va
2046
+ *
2047
+ * Examples:
2048
+ * v_adv = slot.v_advance
2049
+ *
2050
+ */
2051
+ static VALUE ft_glyphslot_v_advance(VALUE self) {
2052
+ FT_GlyphSlot *glyph;
2053
+
2054
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2055
+ return rb_float_new(ft_fixed_to_double((*glyph)->linearVertAdvance));
2056
+ }
2057
+
2058
+ /*
2059
+ * Get the transformed advance width for a FT2::GlyphSlot object.
2060
+ *
2061
+ * Examples:
2062
+ * adv = slot.advance
2063
+ *
2064
+ */
2065
+ static VALUE ft_glyphslot_advance(VALUE self) {
2066
+ FT_GlyphSlot *glyph;
2067
+ VALUE ary;
2068
+
2069
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2070
+ ary = rb_ary_new();
2071
+
2072
+ rb_ary_push(ary, INT2NUM((*glyph)->advance.x));
2073
+ rb_ary_push(ary, INT2NUM((*glyph)->advance.y));
2074
+ return ary;
2075
+ }
2076
+
2077
+ /*
2078
+ * Get the format of a FT2::GlyphSlot object.
2079
+ *
2080
+ * Glyph Formats:
2081
+ * FT2::GlyphFormat::COMPOSITE
2082
+ * FT2::GlyphFormat::BITMAP
2083
+ * FT2::GlyphFormat::OUTLINE
2084
+ * FT2::GlyphFormat::PLOTTER
2085
+ *
2086
+ * Examples:
2087
+ * fmt = slot.format
2088
+ *
2089
+ */
2090
+ static VALUE ft_glyphslot_format(VALUE self) {
2091
+ FT_GlyphSlot *glyph;
2092
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2093
+ return INT2NUM((*glyph)->format);
2094
+ }
2095
+
2096
+ /*
2097
+ * Get the bitmap of a bitmap format FT2::GlyphSlot object.
2098
+ *
2099
+ * Examples:
2100
+ * bmap = slot.bitmap
2101
+ *
2102
+ */
2103
+ static VALUE ft_glyphslot_bitmap(VALUE self) {
2104
+ FT_GlyphSlot *glyph;
2105
+ FT_Bitmap *bitmap;
2106
+
2107
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2108
+ bitmap = malloc(sizeof(FT_Bitmap));
2109
+ *bitmap = (*glyph)->bitmap;
2110
+
2111
+ return Data_Wrap_Struct(cBitmap, 0, dont_free, bitmap);
2112
+ }
2113
+
2114
+ /*
2115
+ * Get the left bearing (in pixels) of a bitmap format FT2::GlyphSlot object.
2116
+ *
2117
+ * Note:
2118
+ * Only valid if the format is FT2::GlyphFormat::BITMAP.
2119
+ *
2120
+ * Examples:
2121
+ * left = slot.bitmap_left
2122
+ *
2123
+ */
2124
+ static VALUE ft_glyphslot_bitmap_left(VALUE self) {
2125
+ FT_GlyphSlot *glyph;
2126
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2127
+ return INT2NUM((*glyph)->bitmap_left);
2128
+ }
2129
+
2130
+ /*
2131
+ * Get the top bearing (in pixels) of a bitmap format FT2::GlyphSlot object.
2132
+ *
2133
+ * Note:
2134
+ * Only valid if the format is FT2::GlyphFormat::BITMAP. The value
2135
+ * returned is the distance from the baseline to the topmost glyph
2136
+ * scanline, upwards y-coordinates being positive.
2137
+ *
2138
+ * Examples:
2139
+ * top = slot.bitmap_top
2140
+ *
2141
+ */
2142
+ static VALUE ft_glyphslot_bitmap_top(VALUE self) {
2143
+ FT_GlyphSlot *glyph;
2144
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2145
+ return INT2NUM((*glyph)->bitmap_top);
2146
+ }
2147
+
2148
+ /*
2149
+ * Get the outline of a bitmap outline format FT2::GlyphSlot object.
2150
+ *
2151
+ * Note:
2152
+ * Only valid if the format is FT2::GlyphFormat::OUTLINE.
2153
+ *
2154
+ * Examples:
2155
+ * outline = slot.outline
2156
+ *
2157
+ */
2158
+ static VALUE ft_glyphslot_outline(VALUE self) {
2159
+ FT_GlyphSlot *glyph;
2160
+ FT_Outline *outline;
2161
+
2162
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2163
+ outline = malloc(sizeof(FT_Outline));
2164
+ *outline = (*glyph)->outline;
2165
+
2166
+ return Data_Wrap_Struct(cOutline, 0, dont_free, outline);
2167
+ }
2168
+
2169
+ /*
2170
+ * Get the number of subglyphs of a FT2::GlyphSlot object.
2171
+ *
2172
+ * Note:
2173
+ * Only valid if the format is FT2::GlyphFormat::COMPOSITE.
2174
+ *
2175
+ * Examples:
2176
+ * outline = slot.outline
2177
+ *
2178
+ */
2179
+ static VALUE ft_glyphslot_num_subglyphs(VALUE self) {
2180
+ FT_GlyphSlot *glyph;
2181
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2182
+ return INT2NUM((*glyph)->num_subglyphs);
2183
+ }
2184
+
2185
+ /*
2186
+ * Get a list of subglyphs of a composite format FT2::GlyphSlot object.
2187
+ *
2188
+ * Note:
2189
+ * Only valid if the format is FT2::GlyphFormat::COMPOSITE. FIXME:
2190
+ * this method may not work correctly at the moment.
2191
+ *
2192
+ * Examples:
2193
+ * sub_glyphs = slot.subglyphs
2194
+ *
2195
+ */
2196
+ static VALUE ft_glyphslot_subglyphs(VALUE self) {
2197
+ FT_GlyphSlot *glyph;
2198
+ VALUE rtn;
2199
+ int num;
2200
+
2201
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2202
+ if ((num = (*glyph)->num_subglyphs) < 1)
2203
+ return Qnil;
2204
+
2205
+ /* FIXME: this probably doesn't work */
2206
+ rtn = rb_ary_new();
2207
+ /*
2208
+ * for (i = 0; i < num; i++)
2209
+ * rb_ary_push(rtn, Data_Wrap_Struct(cSubGlyph, 0,
2210
+ * dont_free,
2211
+ * (*glyph)->subglyphs[i]));
2212
+ */
2213
+ return rtn;
2214
+ }
2215
+
2216
+ /*
2217
+ * Get optional control data for a FT2::GlyphSlot object.
2218
+ *
2219
+ * Description:
2220
+ * Certain font drivers can also return the control data for a given
2221
+ * FT2::GlyphSlot (e.g. TrueType bytecode, Type 1 charstrings, etc.).
2222
+ * This field is a pointer to such data.
2223
+ *
2224
+ * Examples:
2225
+ * data = slot.control_data
2226
+ *
2227
+ */
2228
+ static VALUE ft_glyphslot_control_data(VALUE self) {
2229
+ FT_GlyphSlot *glyph;
2230
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2231
+ return rb_str_new((*glyph)->control_data, (*glyph)->control_len);
2232
+ }
2233
+
2234
+ /*
2235
+ * Get the length of the optional control data for a FT2::GlyphSlot object.
2236
+ *
2237
+ * Examples:
2238
+ * len = slot.control_len
2239
+ *
2240
+ */
2241
+ static VALUE ft_glyphslot_control_len(VALUE self) {
2242
+ FT_GlyphSlot *glyph;
2243
+ Data_Get_Struct(self, FT_GlyphSlot, glyph);
2244
+ return INT2NUM((*glyph)->control_len);
2245
+ }
2246
+
2247
+
2248
+ /*********************/
2249
+ /* FT2::Size methods */
2250
+ /*********************/
2251
+
2252
+ /*
2253
+ * Constructor for FT2::Size class.
2254
+ *
2255
+ * This method is currently empty. You should never call this method
2256
+ * directly unless you're instantiating a derived class (ie, you know
2257
+ * what you're doing).
2258
+ *
2259
+ */
2260
+ static VALUE ft_size_init(VALUE self) {
2261
+ return self;
2262
+ }
2263
+
2264
+ /*
2265
+ * Get the FT2::Face object this FT2::Size object is associated with.
2266
+ *
2267
+ * Examples:
2268
+ * face = size.face
2269
+ *
2270
+ */
2271
+ static VALUE ft_size_face(VALUE self) {
2272
+ FT_Size *size;
2273
+ FT_Face *face;
2274
+
2275
+ Data_Get_Struct(self, FT_Size, size);
2276
+ face = malloc(sizeof(FT_Face));
2277
+ *face = (*size)->face;
2278
+
2279
+ return Data_Wrap_Struct(cFace, 0, dont_free, face);
2280
+ }
2281
+
2282
+ /*
2283
+ * Get the FT2::SizeMetrics associated with a FT2::Size object.
2284
+ *
2285
+ * Examples:
2286
+ * s_metrics = size.metrics
2287
+ *
2288
+ */
2289
+ static VALUE ft_size_metrics(VALUE self) {
2290
+ FT_Size *size;
2291
+ FT_Size_Metrics *metrics;
2292
+
2293
+ Data_Get_Struct(self, FT_Size, size);
2294
+ metrics = malloc(sizeof(FT_Size_Metrics));
2295
+ *metrics = (*size)->metrics;
2296
+
2297
+ return Data_Wrap_Struct(cSizeMetrics, 0, dont_free, metrics);
2298
+ }
2299
+
2300
+
2301
+ /****************************/
2302
+ /* FT2::SizeMetrics methods */
2303
+ /****************************/
2304
+
2305
+ /*
2306
+ * Constructor for FT2::SizeMetrics class.
2307
+ *
2308
+ * This method is currently empty. You should never call this method
2309
+ * directly unless you're instantiating a derived class (ie, you know
2310
+ * what you're doing).
2311
+ *
2312
+ */
2313
+ static VALUE ft_size_metrics_init(VALUE self) {
2314
+ return self;
2315
+ }
2316
+
2317
+ /*
2318
+ * Get the X pixels per EM of this FT2::SizeMetrics object.
2319
+ *
2320
+ * Description:
2321
+ * x_ppem stands for the size in integer pixels of the EM square.
2322
+ * which also is the horizontal character pixel size.
2323
+ *
2324
+ * Examples:
2325
+ * x_ppem = face.size.metrics.x_ppem
2326
+ *
2327
+ */
2328
+ static VALUE ft_size_metrics_x_ppem(VALUE self) {
2329
+ FT_Size_Metrics *size_metrics;
2330
+ Data_Get_Struct(self, FT_Size_Metrics, size_metrics);
2331
+ return INT2FIX((int) (*size_metrics).x_ppem);
2332
+ }
2333
+
2334
+ /*
2335
+ * Get the Y pixels per EM of this FT2::SizeMetrics object.
2336
+ *
2337
+ * Description:
2338
+ * y_ppem stands for the size in integer pixels of the EM square.
2339
+ * which also is the vertical character pixel size.
2340
+ *
2341
+ * Examples:
2342
+ * y_ppem = face.size.metrics.y_ppem
2343
+ *
2344
+ */
2345
+ static VALUE ft_size_metrics_y_ppem(VALUE self) {
2346
+ FT_Size_Metrics *size_metrics;
2347
+ Data_Get_Struct(self, FT_Size_Metrics, size_metrics);
2348
+ return INT2FIX((int) (*size_metrics).y_ppem);
2349
+ }
2350
+
2351
+ /*
2352
+ * Get the horizontal scale of a FT2::SizeMetrics object.
2353
+ *
2354
+ * Description:
2355
+ * Scale that is used to directly scale horizontal distances from
2356
+ * design space to 1/64th of device pixels.
2357
+ *
2358
+ * Examples:
2359
+ * x_scale = face.size.metrics.x_scale
2360
+ *
2361
+ */
2362
+ static VALUE ft_size_metrics_x_scale(VALUE self) {
2363
+ FT_Size_Metrics *size_metrics;
2364
+ Data_Get_Struct(self, FT_Size_Metrics, size_metrics);
2365
+ return INT2FIX((int) (*size_metrics).x_scale);
2366
+ }
2367
+
2368
+ /*
2369
+ * Get the vertical scale of a FT2::SizeMetrics object.
2370
+ *
2371
+ * Description:
2372
+ * Scale that is used to directly scale vertical distances from
2373
+ * design space to 1/64th of device pixels.
2374
+ *
2375
+ * Examples:
2376
+ * y_scale = face.size.metrics.y_scale
2377
+ *
2378
+ */
2379
+ static VALUE ft_size_metrics_y_scale(VALUE self) {
2380
+ FT_Size_Metrics *size_metrics;
2381
+ Data_Get_Struct(self, FT_Size_Metrics, size_metrics);
2382
+ return INT2FIX((int) (*size_metrics).y_scale);
2383
+ }
2384
+
2385
+
2386
+ /**********************/
2387
+ /* FT2::Glyph methods */
2388
+ /**********************/
2389
+ static void glyph_free(void *ptr) {
2390
+ FT_Glyph glyph = *((FT_Glyph *) ptr);
2391
+ FT_Done_Glyph(glyph);
2392
+ free(ptr);
2393
+ }
2394
+
2395
+
2396
+ /*
2397
+ * Constructor for FT2::Glyph class.
2398
+ *
2399
+ * This method is currently empty. You should never call this method
2400
+ * directly unless you're instantiating a derived class (ie, you know
2401
+ * what you're doing).
2402
+ *
2403
+ */
2404
+ static VALUE ft_glyph_init(VALUE self) {
2405
+ return self;
2406
+ }
2407
+
2408
+ /*
2409
+ * Get the library of a FT2::Glyph object.
2410
+ *
2411
+ * Note:
2412
+ * Glyph objects are not owned or tracked by the library.
2413
+ *
2414
+ * Examples:
2415
+ * lib = glyph.library
2416
+ *
2417
+ */
2418
+ static VALUE ft_glyph_library(VALUE self) {
2419
+ FT_Glyph *glyph;
2420
+ Data_Get_Struct(self, FT_Glyph, glyph);
2421
+ return Data_Wrap_Struct(cLibrary, 0, dont_free, (*glyph)->library);
2422
+ }
2423
+
2424
+ /*
2425
+ * Get the FreeType2 class of a FT2::Glyph object.
2426
+ *
2427
+ * Note:
2428
+ * This is _not_ the Ruby class of the object.
2429
+ *
2430
+ * Aliases:
2431
+ * FT2::Glyph#clazz
2432
+ *
2433
+ * Examples:
2434
+ * c = glyph.class
2435
+ *
2436
+ */
2437
+ static VALUE ft_glyph_class(VALUE self) {
2438
+ FT_Glyph *glyph;
2439
+ Data_Get_Struct(self, FT_Glyph, glyph);
2440
+ return Data_Wrap_Struct(cGlyphClass, 0, dont_free, &(*glyph)->clazz);
2441
+ }
2442
+
2443
+ /*
2444
+ * Get the format of a FT2::Glyph object's image.
2445
+ *
2446
+ * Glyph Formats:
2447
+ * FT2::GlyphFormat::COMPOSITE
2448
+ * FT2::GlyphFormat::BITMAP
2449
+ * FT2::GlyphFormat::OUTLINE
2450
+ * FT2::GlyphFormat::PLOTTER
2451
+ *
2452
+ * Examples:
2453
+ * format = glyph.format
2454
+ *
2455
+ */
2456
+ static VALUE ft_glyph_format(VALUE self) {
2457
+ FT_Glyph *glyph;
2458
+ Data_Get_Struct(self, FT_Glyph, glyph);
2459
+ return INT2FIX((*glyph)->format);
2460
+ }
2461
+
2462
+ /*
2463
+ * Get the advance of a FT2::Glyph object.
2464
+ *
2465
+ * Description:
2466
+ * This vector gives the FT2::Glyph object's advance width.
2467
+ *
2468
+ * Examples:
2469
+ * advance = glyph.advance
2470
+ *
2471
+ */
2472
+ static VALUE ft_glyph_advance(VALUE self) {
2473
+ FT_Glyph *glyph;
2474
+ VALUE ary;
2475
+
2476
+ Data_Get_Struct(self, FT_Glyph, glyph);
2477
+ ary = rb_ary_new();
2478
+ rb_ary_push(ary, INT2FIX((*glyph)->advance.x));
2479
+ rb_ary_push(ary, INT2FIX((*glyph)->advance.y));
2480
+
2481
+ return ary;
2482
+ }
2483
+
2484
+ /*
2485
+ * Duplicate a FT2::Glyph object.
2486
+ *
2487
+ * Aliases:
2488
+ * FT2::Glyph#copy
2489
+ *
2490
+ * Examples:
2491
+ * new_glyph = glyph.dup
2492
+ *
2493
+ */
2494
+ static VALUE ft_glyph_dup(VALUE self) {
2495
+ FT_Error err;
2496
+ FT_Glyph *glyph, *new_glyph;
2497
+
2498
+ new_glyph = malloc(sizeof(FT_Glyph));
2499
+ Data_Get_Struct(self, FT_Glyph, glyph);
2500
+ err = FT_Glyph_Copy(*glyph, new_glyph);
2501
+ if (err != FT_Err_Ok)
2502
+ handle_error(err);
2503
+
2504
+ return Data_Wrap_Struct(cGlyph, 0, glyph_free, new_glyph);
2505
+ }
2506
+
2507
+ /*
2508
+ * Transform a FT2::Glyph object if it's format is scalable.
2509
+ *
2510
+ * Description:
2511
+ * matrix: A pointer to a 2x2 matrix to apply.
2512
+ * delta: A pointer to a 2d vector to apply. Coordinates are
2513
+ * expressed in 1/64th of a pixel.
2514
+ *
2515
+ * Note:
2516
+ * The transformation matrix is also applied to the glyph's advance
2517
+ * vector. This method returns an error if the glyph format is not
2518
+ * scalable (eg, if it's not equal to zero).
2519
+ *
2520
+ * Examples:
2521
+ * matrix = [[1, 0],
2522
+ * [0, 1]]
2523
+ * delta = [1, 1]
2524
+ * transform = glyph.transform matrix, delta
2525
+ *
2526
+ */
2527
+ static VALUE ft_glyph_transform(VALUE self, VALUE matrix_ary, VALUE delta_ary) {
2528
+ FT_Error err;
2529
+ FT_Glyph *glyph;
2530
+ FT_Matrix matrix;
2531
+ FT_Vector delta;
2532
+
2533
+ matrix.xx = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix_ary, 0), 0)));
2534
+ matrix.xy = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix_ary, 0), 1)));
2535
+ matrix.yx = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix_ary, 1), 0)));
2536
+ matrix.yy = DBL2FTFIX(NUM2DBL(rb_ary_entry(rb_ary_entry(matrix_ary, 1), 1)));
2537
+
2538
+ delta.x = NUM2INT(rb_ary_entry(delta_ary, 0));
2539
+ delta.y = NUM2INT(rb_ary_entry(delta_ary, 1));
2540
+
2541
+ Data_Get_Struct(self, FT_Glyph, glyph);
2542
+ err = FT_Glyph_Transform(*glyph, &matrix, &delta);
2543
+ if (err != FT_Err_Ok)
2544
+ handle_error(err);
2545
+
2546
+ return self;
2547
+ }
2548
+
2549
+ /*
2550
+ * Get the control box of a FT2::Glyph object.
2551
+ *
2552
+ * Description:
2553
+ * Returns a FT2::Glyph object's `control box'. The control box
2554
+ * encloses all the outline's points, including Bezier control points.
2555
+ * Though it coincides with the exact bounding box for most FT2::Glyph
2556
+ * objects, it can be slightly larger in some situations (like when
2557
+ * rotating an outline which contains Bezier outside arcs).
2558
+ *
2559
+ * Computing the control box is very fast, while getting the bounding
2560
+ * box can take much more time as it needs to walk over all segments
2561
+ * and arcs in the outline. To get the latter, you can use the
2562
+ * `ftbbox' component which is dedicated to this single task.
2563
+ *
2564
+ * Notes:
2565
+ * Coordinates are relative to the FT2::Glyph object's origin, using
2566
+ * the Y-upwards convention.
2567
+ *
2568
+ * If the FT2::Glyph object has been loaded with FT2::Load::NO_SCALE,
2569
+ * `bbox_mode' must be set to FT2::GlyphBBox::UNSCALED to get unscaled
2570
+ * font units.
2571
+ *
2572
+ * If `bbox_mode' is set to FT2::GlyphBBox::SUBPIXELS the
2573
+ * bbox coordinates are returned in 26.6 pixels (i.e. 1/64th of
2574
+ * pixels).
2575
+ *
2576
+ * Note that the maximum coordinates are exclusive, which means that
2577
+ * one can compute the width and height of the FT2::Glyph object image
2578
+ * (be it in integer or 26.6 pixels) as:
2579
+ *
2580
+ * width = bbox.xMax - bbox.xMin; height = bbox.yMax - bbox.yMin;
2581
+ *
2582
+ * Note also that for 26.6 coordinates, if `bbox_mode' is set to
2583
+ * FT2::GlyphBBox::GRIDFIT, the coordinates will also be
2584
+ * grid-fitted, which corresponds to:
2585
+ *
2586
+ * bbox.xMin = FLOOR(bbox.xMin); bbox.yMin = FLOOR(bbox.yMin);
2587
+ * bbox.xMax = CEILING(bbox.xMax); bbox.yMax = CEILING(bbox.yMax);
2588
+ *
2589
+ * To get the bbox in pixel coordinates, set `bbox_mode' to
2590
+ * FT2::GlyphBBox::TRUNCATE.
2591
+ *
2592
+ * To get the bbox in grid-fitted pixel coordinates, set `bbox_mode'
2593
+ * to FT2::GlyphBBox::PIXELS.
2594
+ *
2595
+ * The default value for `bbox_mode' is FT2::GlyphBBox::PIXELS.
2596
+ *
2597
+ * Aliases:
2598
+ * FT2::Glyph#control_box
2599
+ *
2600
+ * Examples:
2601
+ * bbox_mode = FT2::GlyphBBox::PIXELS
2602
+ * x_min, y_min, x_max, y_max = glyph.cbox bbox_mode
2603
+ *
2604
+ */
2605
+ static VALUE ft_glyph_cbox(VALUE self, VALUE bbox_mode) {
2606
+ FT_Glyph *glyph;
2607
+ FT_BBox bbox;
2608
+ VALUE ary;
2609
+
2610
+ Data_Get_Struct(self, FT_Glyph, glyph);
2611
+ FT_Glyph_Get_CBox(*glyph, FIX2INT(bbox_mode), &bbox);
2612
+
2613
+ ary = rb_ary_new();
2614
+ rb_ary_push(ary, INT2FIX(bbox.xMin));
2615
+ rb_ary_push(ary, INT2FIX(bbox.yMin));
2616
+ rb_ary_push(ary, INT2FIX(bbox.xMax));
2617
+ rb_ary_push(ary, INT2FIX(bbox.yMax));
2618
+
2619
+ return ary;
2620
+ }
2621
+
2622
+ /*
2623
+ * Render a FT2::Glyph object as a FT2::BitmapGlyph object.
2624
+ *
2625
+ * Description:
2626
+ * Converts a FT2::Glyph object to a FT2::BitmapGlyph object.
2627
+ *
2628
+ * render_mode: A set of bit flags that describe how the data is.
2629
+ * origin: A vector used to translate the glyph image before
2630
+ * rendering. Can be nil (if no translation). The
2631
+ * origin is expressed in 26.6 pixels.
2632
+ * destroy: A boolean that indicates that the original glyph
2633
+ * image should be destroyed by this function. It is
2634
+ * never destroyed in case of error.
2635
+ *
2636
+ * Aliases:
2637
+ * FT2::Glyph#to_bitmap
2638
+ *
2639
+ * Examples:
2640
+ * glyph_to_bmap = glyph.glyph_to_bmap
2641
+ *
2642
+ */
2643
+ static VALUE ft_glyph_to_bmap(VALUE self, VALUE render_mode, VALUE origin, VALUE destroy) {
2644
+ FT_Error err;
2645
+ FT_Glyph *glyph;
2646
+ FT_Vector v;
2647
+ FT_Bool d;
2648
+
2649
+ Data_Get_Struct(self, FT_Glyph, glyph);
2650
+ v.x = NUM2INT(rb_ary_entry(origin, 0));
2651
+ v.y = NUM2INT(rb_ary_entry(origin, 1));
2652
+ d = (destroy != Qnil) ? 1 : 0;
2653
+
2654
+ err = FT_Glyph_To_Bitmap(glyph, FIX2INT(render_mode), &v, d);
2655
+ if (err != FT_Err_Ok)
2656
+ handle_error(err);
2657
+
2658
+ return self;
2659
+ }
2660
+
2661
+
2662
+ /****************************/
2663
+ /* FT2::BitmapGlyph methods */
2664
+ /****************************/
2665
+
2666
+ /*
2667
+ * Constructor for FT2::BitmapGlyph class.
2668
+ *
2669
+ * This method is currently empty. You should never call this method
2670
+ * directly unless you're instantiating a derived class (ie, you know
2671
+ * what you're doing).
2672
+ *
2673
+ */
2674
+ static VALUE ft_bmapglyph_init(VALUE self) {
2675
+ return self;
2676
+ }
2677
+
2678
+ /*
2679
+ * Get the top-side bearing of a BitmapGlyph object.
2680
+ *
2681
+ * Description:
2682
+ * The top-side bearing, i.e., the vertical distance from the current
2683
+ * pen position to the top border of the glyph bitmap. This distance
2684
+ * is positive for upwards-y.
2685
+ *
2686
+ * Note:
2687
+ * FT2::BitmapGlyph is a subclass of FT2::Glyph.
2688
+ *
2689
+ * Examples:
2690
+ * y = bmap_glyph.top
2691
+ *
2692
+ */
2693
+ static VALUE ft_bmapglyph_top(VALUE self) {
2694
+ FT_BitmapGlyph *glyph;
2695
+ Data_Get_Struct(self, FT_BitmapGlyph, glyph);
2696
+ return INT2FIX((*glyph)->top);
2697
+ }
2698
+
2699
+ /*
2700
+ * Get the left-side bearing of a BitmapGlyph object.
2701
+ *
2702
+ * Description:
2703
+ * The left-side bearing, i.e., the horizontal distance from the
2704
+ * current pen position to the left border of the glyph bitmap.
2705
+ *
2706
+ * Note:
2707
+ * FT2::BitmapGlyph is a subclass of FT2::Glyph.
2708
+ *
2709
+ * Examples:
2710
+ * x = bmap_glyph.left
2711
+ *
2712
+ */
2713
+ static VALUE ft_bmapglyph_left(VALUE self) {
2714
+ FT_BitmapGlyph *glyph;
2715
+ Data_Get_Struct(self, FT_BitmapGlyph, glyph);
2716
+ return INT2FIX((*glyph)->left);
2717
+ }
2718
+
2719
+ /*
2720
+ * Get the FT2::Bitmap of a FT2::BitmapGlyph object.
2721
+ *
2722
+ * Examples:
2723
+ * bmap = bmap_glyph.bitmap
2724
+ *
2725
+ */
2726
+ static VALUE ft_bmapglyph_bitmap(VALUE self) {
2727
+ FT_BitmapGlyph *glyph;
2728
+ Data_Get_Struct(self, FT_BitmapGlyph, glyph);
2729
+ return Data_Wrap_Struct(cBitmapGlyph, 0, glyph_free, &(*glyph)->bitmap);
2730
+ }
2731
+
2732
+
2733
+ /*****************************/
2734
+ /* FT2::OutlineGlyph methods */
2735
+ /*****************************/
2736
+
2737
+ /*
2738
+ * Constructor for FT2::OutlineGlyph class.
2739
+ *
2740
+ * This method is currently empty. You should never call this method
2741
+ * directly unless you're instantiating a derived class (ie, you know
2742
+ * what you're doing).
2743
+ *
2744
+ */
2745
+ static VALUE ft_outlineglyph_init(VALUE self) {
2746
+ return self;
2747
+ }
2748
+
2749
+ /*
2750
+ * Get the outline of a FT2::OutlineGlyph object.
2751
+ *
2752
+ * Note:
2753
+ * FT2::OutlineGlyph is a subclass of FT2::Glyph.
2754
+ *
2755
+ * Examples:
2756
+ * outline = oline.outline
2757
+ *
2758
+ */
2759
+ static VALUE ft_outlineglyph_outline(VALUE self) {
2760
+ FT_OutlineGlyph *glyph;
2761
+ Data_Get_Struct(self, FT_OutlineGlyph, glyph);
2762
+ return Data_Wrap_Struct(cOutline, 0, dont_free, &(*glyph)->outline);
2763
+ }
2764
+ static void define_constants(void) {
2765
+ /***********************************/
2766
+ /* define FT2::PixelMode constants */
2767
+ /***********************************/
2768
+ mPixelMode = rb_define_module_under(mFt2, "PixelMode");
2769
+ rb_define_const(mPixelMode, "NONE", INT2FIX(FT_PIXEL_MODE_NONE));
2770
+ rb_define_const(mPixelMode, "MONO", INT2FIX(FT_PIXEL_MODE_MONO));
2771
+ rb_define_const(mPixelMode, "GRAY2", INT2FIX(FT_PIXEL_MODE_GRAY2));
2772
+ rb_define_const(mPixelMode, "GRAY4", INT2FIX(FT_PIXEL_MODE_GRAY4));
2773
+ rb_define_const(mPixelMode, "LCD", INT2FIX(FT_PIXEL_MODE_LCD));
2774
+ rb_define_const(mPixelMode, "LCD_V", INT2FIX(FT_PIXEL_MODE_LCD_V));
2775
+ rb_define_const(mPixelMode, "MAX", INT2FIX(FT_PIXEL_MODE_MAX));
2776
+
2777
+ /* old pixel mode stuff (according to tutorial)
2778
+ rb_define_const(mPixelMode, "NONE", INT2FIX(ft_pixel_mode_none));
2779
+ rb_define_const(mPixelMode, "MONO", INT2FIX(ft_pixel_mode_mono));
2780
+ rb_define_const(mPixelMode, "GRAYS", INT2FIX(ft_pixel_mode_grays));
2781
+ rb_define_const(mPixelMode, "PAL2", INT2FIX(ft_pixel_mode_pal2));
2782
+ rb_define_const(mPixelMode, "PAL4", INT2FIX(ft_pixel_mode_pal4));
2783
+ rb_define_const(mPixelMode, "PAL8", INT2FIX(ft_pixel_mode_pal8));
2784
+ rb_define_const(mPixelMode, "RGB15", INT2FIX(ft_pixel_mode_rgb15));
2785
+ rb_define_const(mPixelMode, "RGB16", INT2FIX(ft_pixel_mode_rgb16));
2786
+ rb_define_const(mPixelMode, "RGB24", INT2FIX(ft_pixel_mode_rgb24));
2787
+ rb_define_const(mPixelMode, "RGB32", INT2FIX(ft_pixel_mode_rgb32));
2788
+ */
2789
+
2790
+ /*************************************/
2791
+ /* define FT2::PaletteMode constants */
2792
+ /*************************************/
2793
+ /* FIXME: doesn't compile, so I'm disabling it for now
2794
+ mPaletteMode = rb_define_module_under(mFt2, "PaletteMode");
2795
+ rb_define_const(mPaletteMode, "RGB", INT2FIX(ft_palette_mode_rgb));
2796
+ rb_define_const(mPaletteMode, "RGBA", INT2FIX(ft_palette_mode_rgba));
2797
+ */
2798
+
2799
+ /*************************************/
2800
+ /* define FT2::GlyphFormat constants */
2801
+ /*************************************/
2802
+ mGlyphFormat = rb_define_module_under(mFt2, "GlyphFormat");
2803
+ rb_define_const(mGlyphFormat, "COMPOSITE", INT2FIX(ft_glyph_format_composite));
2804
+ rb_define_const(mGlyphFormat, "BITMAP", INT2FIX(ft_glyph_format_bitmap));
2805
+ rb_define_const(mGlyphFormat, "OUTLINE", INT2FIX(ft_glyph_format_outline));
2806
+ rb_define_const(mGlyphFormat, "PLOTTER", INT2FIX(ft_glyph_format_plotter));
2807
+
2808
+ /**********************************/
2809
+ /* define FT2::Encoding constants */
2810
+ /**********************************/
2811
+ mEnc = rb_define_module_under(mFt2, "Encoding");
2812
+ rb_define_const(mEnc, "NONE", INT2FIX(ft_encoding_none));
2813
+ rb_define_const(mEnc, "SYMBOL", INT2FIX(ft_encoding_symbol));
2814
+ rb_define_const(mEnc, "UNICODE", INT2FIX(ft_encoding_unicode));
2815
+ rb_define_const(mEnc, "LATIN_1", INT2FIX(ft_encoding_latin_1));
2816
+ /* disabled as per the ft2 header documentation */
2817
+ /* rb_define_const(mEnc, "LATIN_2", INT2FIX(ft_encoding_latin_2)); */
2818
+ rb_define_const(mEnc, "SJIS", INT2FIX(ft_encoding_sjis));
2819
+ rb_define_const(mEnc, "GB2312", INT2FIX(ft_encoding_gb2312));
2820
+ rb_define_const(mEnc, "BIG5", INT2FIX(ft_encoding_big5));
2821
+ rb_define_const(mEnc, "WANSUNG", INT2FIX(ft_encoding_wansung));
2822
+ rb_define_const(mEnc, "JOHAB", INT2FIX(ft_encoding_johab));
2823
+ rb_define_const(mEnc, "ADOBE_STANDARD", INT2FIX(ft_encoding_adobe_standard));
2824
+ rb_define_const(mEnc, "ADOBE_EXPERT", INT2FIX(ft_encoding_adobe_expert));
2825
+ rb_define_const(mEnc, "ADOBE_CUSTOM", INT2FIX(ft_encoding_adobe_custom));
2826
+ rb_define_const(mEnc, "APPLE_ROMAN", INT2FIX(ft_encoding_apple_roman));
2827
+
2828
+ /************************************/
2829
+ /* define FT2::RenderMode constants */
2830
+ /************************************/
2831
+ mRenderMode = rb_define_module_under(mFt2, "RenderMode");
2832
+ rb_define_const(mRenderMode, "NORMAL", INT2FIX(ft_render_mode_normal));
2833
+ rb_define_const(mRenderMode, "MONO", INT2FIX(ft_render_mode_mono));
2834
+
2835
+ /*************************************/
2836
+ /* define FT2::KerningMode constants */
2837
+ /*************************************/
2838
+ mKerningMode = rb_define_module_under(mFt2, "KerningMode");
2839
+ rb_define_const(mKerningMode, "DEFAULT", INT2FIX(ft_kerning_default));
2840
+ rb_define_const(mKerningMode, "UNFITTED", INT2FIX(ft_kerning_unfitted));
2841
+ rb_define_const(mKerningMode, "UNSCALED", INT2FIX(ft_kerning_unscaled));
2842
+
2843
+ /******************************/
2844
+ /* define FT2::Load constants */
2845
+ /******************************/
2846
+ mLoad = rb_define_module_under(mFt2, "Load");
2847
+ rb_define_const(mLoad, "DEFAULT", INT2NUM(FT_LOAD_DEFAULT));
2848
+ rb_define_const(mLoad, "RENDER", INT2NUM(FT_LOAD_RENDER));
2849
+ rb_define_const(mLoad, "MONOCHROME", INT2NUM(FT_LOAD_MONOCHROME));
2850
+ rb_define_const(mLoad, "LINEAR_DESIGN", INT2NUM(FT_LOAD_LINEAR_DESIGN));
2851
+ rb_define_const(mLoad, "NO_SCALE", INT2NUM(FT_LOAD_NO_SCALE));
2852
+ rb_define_const(mLoad, "NO_HINTING", INT2NUM(FT_LOAD_NO_HINTING));
2853
+ rb_define_const(mLoad, "NO_BITMAP", INT2NUM(FT_LOAD_NO_BITMAP));
2854
+ rb_define_const(mLoad, "CROP_BITMAP", INT2NUM(FT_LOAD_CROP_BITMAP));
2855
+ rb_define_const(mLoad, "VERTICAL_LAYOUT", INT2NUM(FT_LOAD_VERTICAL_LAYOUT));
2856
+ rb_define_const(mLoad, "IGNORE_TRANSFORM", INT2NUM(FT_LOAD_IGNORE_TRANSFORM));
2857
+ rb_define_const(mLoad, "IGNORE_GLOBAL_ADVANCE_WIDTH", INT2NUM(FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH));
2858
+ rb_define_const(mLoad, "FORCE_AUTOHINT", INT2NUM(FT_LOAD_FORCE_AUTOHINT));
2859
+ rb_define_const(mLoad, "NO_RECURSE", INT2NUM(FT_LOAD_NO_RECURSE));
2860
+ rb_define_const(mLoad, "PEDANTIC", INT2NUM(FT_LOAD_PEDANTIC));
2861
+
2862
+ /***********************************/
2863
+ /* define FT2::GlyphBBox constants */
2864
+ /***********************************/
2865
+ mBBox = rb_define_module_under(mFt2, "GlyphBBox");
2866
+ rb_define_const(mBBox, "UNSCALED", INT2NUM(ft_glyph_bbox_unscaled));
2867
+ rb_define_const(mBBox, "SUBPIXELS", INT2NUM(ft_glyph_bbox_subpixels));
2868
+ rb_define_const(mBBox, "GRIDFIT", INT2NUM(ft_glyph_bbox_gridfit));
2869
+ rb_define_const(mBBox, "TRUNCATE", INT2NUM(ft_glyph_bbox_truncate));
2870
+ rb_define_const(mBBox, "PIXELS", INT2NUM(ft_glyph_bbox_pixels));
2871
+ }
2872
+
2873
+ void Init_ft2(void) {
2874
+ FT_Error err;
2875
+
2876
+ if ((err = FT_Init_FreeType(&library)) != FT_Err_Ok)
2877
+ handle_error(err);
2878
+
2879
+ /* define top-level FT2 module */
2880
+ mFt2 = rb_define_module("FT2");
2881
+
2882
+ /* define FT2::VERSION */
2883
+ rb_define_const(mFt2, "VERSION", rb_str_new2(VERSION));
2884
+ rb_define_singleton_method(mFt2, "version", ft_version, 0);
2885
+
2886
+ define_constants();
2887
+
2888
+ /****************************/
2889
+ /* define FT2::Bitmap class */
2890
+ /****************************/
2891
+ cBitmap = rb_define_class_under(mFt2, "Bitmap", rb_cObject);
2892
+ rb_define_singleton_method(cBitmap, "initialize", ft_bitmap_init, 0);
2893
+ rb_define_method(cBitmap, "rows", ft_bitmap_rows, 0);
2894
+ rb_define_method(cBitmap, "width", ft_bitmap_width, 0);
2895
+ rb_define_method(cBitmap, "pitch", ft_bitmap_pitch, 0);
2896
+ rb_define_method(cBitmap, "buffer", ft_bitmap_buffer, 0);
2897
+ rb_define_method(cBitmap, "num_grays", ft_bitmap_num_grays, 0);
2898
+ rb_define_method(cBitmap, "pixel_mode", ft_bitmap_pixel_mode, 0);
2899
+ rb_define_method(cBitmap, "palette_mode", ft_bitmap_palette_mode, 0);
2900
+ rb_define_method(cBitmap, "palette", ft_bitmap_palette, 0);
2901
+
2902
+ /*****************************/
2903
+ /* define FT2::CharMap class */
2904
+ /*****************************/
2905
+ cCharMap = rb_define_class_under(mFt2, "CharMap", rb_cObject);
2906
+
2907
+ /**************************/
2908
+ /* define FT2::Face class */
2909
+ /**************************/
2910
+ cFace = rb_define_class_under(mFt2, "Face", rb_cObject);
2911
+ rb_define_singleton_method(cFace, "new", ft_face_new, -1);
2912
+ rb_define_singleton_method(cFace, "load", ft_face_new, -1);
2913
+ rb_define_singleton_method(cFace, "new_from_memory", ft_face_new_from_memory, -1);
2914
+
2915
+ rb_define_singleton_method(cFace, "initialize", ft_face_init, 0);
2916
+
2917
+ rb_define_method(cFace, "faces", ft_face_faces, 0);
2918
+ rb_define_alias(cFace, "num_faces", "faces");
2919
+
2920
+ rb_define_method(cFace, "index", ft_face_index, 0);
2921
+ rb_define_alias(cFace, "face_index", "index");
2922
+
2923
+ rb_define_method(cFace, "flags", ft_face_flags, 0);
2924
+ rb_define_alias(cFace, "face_flags", "flags");
2925
+
2926
+ rb_define_const(cFace, "SCALABLE", INT2FIX(FT_FACE_FLAG_SCALABLE));
2927
+ rb_define_const(cFace, "FIXED_SIZES", INT2FIX(FT_FACE_FLAG_FIXED_SIZES));
2928
+ rb_define_const(cFace, "FIXED_WIDTH", INT2FIX(FT_FACE_FLAG_FIXED_WIDTH));
2929
+ rb_define_const(cFace, "FIXED_HORIZONTAL", INT2FIX(FT_FACE_FLAG_HORIZONTAL));
2930
+ rb_define_const(cFace, "FIXED_VERTICAL", INT2FIX(FT_FACE_FLAG_VERTICAL));
2931
+ rb_define_const(cFace, "SFNT", INT2FIX(FT_FACE_FLAG_SFNT));
2932
+ rb_define_const(cFace, "KERNING", INT2FIX(FT_FACE_FLAG_KERNING));
2933
+ rb_define_const(cFace, "MULTIPLE_MASTERS", INT2FIX(FT_FACE_FLAG_MULTIPLE_MASTERS));
2934
+ rb_define_const(cFace, "GLYPH_NAMES", INT2FIX(FT_FACE_FLAG_GLYPH_NAMES));
2935
+ rb_define_const(cFace, "EXTERNAL_STREAM", INT2FIX(FT_FACE_FLAG_EXTERNAL_STREAM));
2936
+ rb_define_const(cFace, "FAST_GLYPHS", INT2FIX(FT_FACE_FLAG_FAST_GLYPHS));
2937
+
2938
+ rb_define_method(cFace, "scalable?", ft_face_flag_scalable, 0);
2939
+ rb_define_method(cFace, "fixed_sizes?", ft_face_flag_fixed_sizes, 0);
2940
+ rb_define_method(cFace, "fixed_width?", ft_face_flag_fixed_width, 0);
2941
+ rb_define_method(cFace, "horizontal?", ft_face_flag_horizontal, 0);
2942
+ rb_define_method(cFace, "vertical?", ft_face_flag_vertical, 0);
2943
+ rb_define_method(cFace, "sfnt?", ft_face_flag_sfnt, 0);
2944
+ rb_define_method(cFace, "kerning?", ft_face_flag_kerning, 0);
2945
+ rb_define_method(cFace, "external_stream?", ft_face_flag_external_stream, 0);
2946
+ rb_define_method(cFace, "fast_glyphs?", ft_face_flag_fast_glyphs, 0);
2947
+
2948
+ rb_define_method(cFace, "style_flags", ft_face_style_flags, 0);
2949
+
2950
+ rb_define_const(cFace, "BOLD", INT2FIX(FT_STYLE_FLAG_BOLD));
2951
+ rb_define_const(cFace, "ITALIC", INT2FIX(FT_STYLE_FLAG_ITALIC));
2952
+
2953
+ rb_define_method(cFace, "bold?", ft_face_flag_bold, 0);
2954
+ rb_define_method(cFace, "italic?", ft_face_flag_italic, 0);
2955
+
2956
+ rb_define_method(cFace, "glyphs", ft_face_glyphs, 0);
2957
+ rb_define_alias(cFace, "num_glyphs", "glyphs");
2958
+
2959
+ rb_define_method(cFace, "family", ft_face_family, 0);
2960
+ rb_define_method(cFace, "style", ft_face_style, 0);
2961
+
2962
+ rb_define_method(cFace, "fixed_sizes", ft_face_fixed_sizes, 0);
2963
+ rb_define_alias(cFace, "num_fixed_sizes", "fixed_sizes");
2964
+
2965
+ rb_define_method(cFace, "available_sizes", ft_face_available_sizes, 0);
2966
+ rb_define_alias(cFace, "num_available_sizes", "available_sizes");
2967
+
2968
+ rb_define_method(cFace, "num_charmaps", ft_face_num_charmaps, 0);
2969
+ rb_define_method(cFace, "charmaps", ft_face_charmaps, 0);
2970
+
2971
+ rb_define_method(cFace, "bbox", ft_face_bbox, 0);
2972
+
2973
+ rb_define_method(cFace, "units_per_em", ft_face_units_per_em, 0);
2974
+ rb_define_alias(cFace, "units_per_EM", "units_per_em");
2975
+
2976
+ rb_define_method(cFace, "ascender", ft_face_ascender, 0);
2977
+ rb_define_method(cFace, "descender", ft_face_descender, 0);
2978
+ rb_define_method(cFace, "height", ft_face_height, 0);
2979
+ rb_define_method(cFace, "max_advance_width", ft_face_max_advance_width, 0);
2980
+ rb_define_method(cFace, "max_advance_height", ft_face_max_advance_height, 0);
2981
+ rb_define_method(cFace, "underline_position", ft_face_underline_position, 0);
2982
+ rb_define_method(cFace, "underline_thickness", ft_face_underline_thickness, 0);
2983
+ rb_define_method(cFace, "glyph", ft_face_glyph, 0);
2984
+ rb_define_method(cFace, "size", ft_face_size, 0);
2985
+ rb_define_method(cFace, "charmap", ft_face_charmap, 0);
2986
+
2987
+ rb_define_method(cFace, "attach", ft_face_attach, 1);
2988
+ rb_define_alias(cFace, "attach_file", "attach");
2989
+
2990
+ rb_define_method(cFace, "load_glyph", ft_face_load_glyph, 2);
2991
+ rb_define_method(cFace, "load_char", ft_face_load_char, 2);
2992
+
2993
+ rb_define_method(cFace, "char_index", ft_face_char_index, 1);
2994
+ rb_define_method(cFace, "name_index", ft_face_name_index, 1);
2995
+
2996
+ rb_define_method(cFace, "kerning", ft_face_kerning, 3);
2997
+ rb_define_alias(cFace, "get_kerning", "kerning");
2998
+
2999
+ rb_define_method(cFace, "glyph_name", ft_face_glyph_name, 1);
3000
+ rb_define_method(cFace, "postscript_name", ft_face_ps_name, 0);
3001
+ rb_define_alias(cFace, "name", "postscript_name");
3002
+
3003
+ rb_define_method(cFace, "select_charmap", ft_face_select_charmap, 1);
3004
+ rb_define_method(cFace, "set_charmap", ft_face_set_charmap, 1);
3005
+ rb_define_alias(cFace, "charmap=", "set_charmap");
3006
+
3007
+ rb_define_method(cFace, "first_char", ft_face_first_char, 0);
3008
+ rb_define_method(cFace, "next_char", ft_face_next_char, 1);
3009
+
3010
+ rb_define_method(cFace, "current_charmap", ft_face_current_charmap, 0);
3011
+
3012
+ rb_define_method(cFace, "set_char_size", ft_face_set_char_size, 4);
3013
+ rb_define_method(cFace, "set_pixel_sizes", ft_face_set_pixel_sizes, 2);
3014
+ rb_define_method(cFace, "set_transform", ft_face_set_transform, 2);
3015
+
3016
+ /**********************************/
3017
+ /* define FT2::GlyphMetrics class */
3018
+ /**********************************/
3019
+ cGlyphMetrics = rb_define_class_under(mFt2, "GlyphMetrics", rb_cObject);
3020
+ rb_define_singleton_method(cGlyphMetrics, "initialize", ft_glyphmetrics_init, 0);
3021
+
3022
+ rb_define_method(cGlyphMetrics, "width", ft_glyphmetrics_width, 0);
3023
+ rb_define_alias(cGlyphMetrics, "w", "width");
3024
+ rb_define_method(cGlyphMetrics, "height", ft_glyphmetrics_height, 0);
3025
+ rb_define_alias(cGlyphMetrics, "h", "height");
3026
+
3027
+ rb_define_method(cGlyphMetrics, "h_bearing_x", ft_glyphmetrics_h_bear_x, 0);
3028
+ rb_define_alias(cGlyphMetrics, "horiBearingX", "h_bearing_x");
3029
+ rb_define_alias(cGlyphMetrics, "h_bear_x", "h_bearing_x");
3030
+ rb_define_alias(cGlyphMetrics, "hbx", "h_bearing_x");
3031
+ rb_define_method(cGlyphMetrics, "h_bearing_y", ft_glyphmetrics_h_bear_y, 0);
3032
+ rb_define_alias(cGlyphMetrics, "horiBearingY", "h_bearing_y");
3033
+ rb_define_alias(cGlyphMetrics, "h_bear_y", "h_bearing_y");
3034
+ rb_define_alias(cGlyphMetrics, "hby", "h_bearing_y");
3035
+ rb_define_method(cGlyphMetrics, "h_advance", ft_glyphmetrics_h_advance, 0);
3036
+ rb_define_alias(cGlyphMetrics, "horiAdvance", "h_advance");
3037
+ rb_define_alias(cGlyphMetrics, "ha", "h_advance");
3038
+
3039
+ rb_define_method(cGlyphMetrics, "v_bearing_x", ft_glyphmetrics_v_bear_x, 0);
3040
+ rb_define_alias(cGlyphMetrics, "vertBearingX", "v_bearing_x");
3041
+ rb_define_alias(cGlyphMetrics, "v_bear_x", "v_bearing_x");
3042
+ rb_define_alias(cGlyphMetrics, "vbx", "v_bearing_x");
3043
+ rb_define_method(cGlyphMetrics, "v_bearing_y", ft_glyphmetrics_v_bear_y, 0);
3044
+ rb_define_alias(cGlyphMetrics, "vertBearingY", "v_bearing_y");
3045
+ rb_define_alias(cGlyphMetrics, "v_bear_y", "v_bearing_y");
3046
+ rb_define_alias(cGlyphMetrics, "vby", "v_bearing_y");
3047
+ rb_define_method(cGlyphMetrics, "v_advance", ft_glyphmetrics_v_advance, 0);
3048
+ rb_define_alias(cGlyphMetrics, "vertAdvance", "v_advance");
3049
+ rb_define_alias(cGlyphMetrics, "va", "v_advance");
3050
+
3051
+ /*******************************/
3052
+ /* define FT2::GlyphSlot class */
3053
+ /*******************************/
3054
+ cGlyphSlot = rb_define_class_under(mFt2, "GlyphSlot", rb_cObject);
3055
+ rb_define_singleton_method(cGlyphSlot, "initialize", ft_glyphslot_init, 0);
3056
+
3057
+ rb_define_method(cGlyphSlot, "library", ft_glyphslot_library, 0);
3058
+ rb_define_method(cGlyphSlot, "face", ft_glyphslot_face, 0);
3059
+ rb_define_method(cGlyphSlot, "next", ft_glyphslot_next, 0);
3060
+ rb_define_method(cGlyphSlot, "flags", ft_glyphslot_flags, 0);
3061
+ rb_define_method(cGlyphSlot, "metrics", ft_glyphslot_metrics, 0);
3062
+
3063
+ rb_define_method(cGlyphSlot, "h_advance", ft_glyphslot_h_advance, 0);
3064
+ rb_define_alias(cGlyphSlot, "linearHoriAdvance", "h_advance");
3065
+ rb_define_alias(cGlyphSlot, "h_adv", "h_advance");
3066
+ rb_define_alias(cGlyphSlot, "ha", "h_advance");
3067
+
3068
+ rb_define_method(cGlyphSlot, "v_advance", ft_glyphslot_v_advance, 0);
3069
+ rb_define_alias(cGlyphSlot, "linearVertAdvance", "h_advance");
3070
+ rb_define_alias(cGlyphSlot, "v_adv", "h_advance");
3071
+ rb_define_alias(cGlyphSlot, "va", "h_advance");
3072
+
3073
+ rb_define_method(cGlyphSlot, "advance", ft_glyphslot_advance, 0);
3074
+ rb_define_method(cGlyphSlot, "format", ft_glyphslot_format, 0);
3075
+ rb_define_method(cGlyphSlot, "bitmap", ft_glyphslot_bitmap, 0);
3076
+ rb_define_method(cGlyphSlot, "bitmap_left", ft_glyphslot_bitmap_left, 0);
3077
+ rb_define_method(cGlyphSlot, "bitmap_top", ft_glyphslot_bitmap_top, 0);
3078
+ rb_define_method(cGlyphSlot, "outline", ft_glyphslot_outline, 0);
3079
+ rb_define_method(cGlyphSlot, "num_subglyphs", ft_glyphslot_num_subglyphs, 0);
3080
+ rb_define_method(cGlyphSlot, "subglyphs", ft_glyphslot_subglyphs, 0);
3081
+ rb_define_method(cGlyphSlot, "control_data", ft_glyphslot_control_data, 0);
3082
+ rb_define_method(cGlyphSlot, "control_len", ft_glyphslot_control_len, 0);
3083
+
3084
+ rb_define_method(cGlyphSlot, "render", ft_glyphslot_render, 1);
3085
+ rb_define_alias(cGlyphSlot, "render_glyph", "render");
3086
+
3087
+ rb_define_method(cGlyphSlot, "glyph", ft_glyphslot_glyph, 0);
3088
+ rb_define_alias(cGlyphSlot, "get_glyph", "glyph");
3089
+
3090
+ /*****************************/
3091
+ /* define FT2::Library class */
3092
+ /*****************************/
3093
+ cLibrary = rb_define_class_under(mFt2, "Library", rb_cObject);
3094
+
3095
+ /****************************/
3096
+ /* define FT2::Memory class */
3097
+ /****************************/
3098
+ cMemory = rb_define_class_under(mFt2, "Memory", rb_cObject);
3099
+
3100
+ /*****************************/
3101
+ /* define FT2::Outline class */
3102
+ /*****************************/
3103
+ cOutline = rb_define_class_under(mFt2, "Outline", rb_cObject);
3104
+
3105
+ /**************************/
3106
+ /* define FT2::Size class */
3107
+ /**************************/
3108
+ cSize = rb_define_class_under(mFt2, "Size", rb_cObject);
3109
+ rb_define_singleton_method(cSize, "initialize", ft_size_init, 0);
3110
+ rb_define_method(cSize, "face", ft_size_face, 0);
3111
+ rb_define_method(cSize, "metrics", ft_size_metrics, 0);
3112
+
3113
+ /*********************************/
3114
+ /* define FT2::SizeMetrics class */
3115
+ /*********************************/
3116
+ cSizeMetrics = rb_define_class_under(mFt2, "SizeMetrics", rb_cObject);
3117
+ rb_define_singleton_method(cSizeMetrics, "initialize", ft_size_metrics_init, 0);
3118
+ rb_define_method(cSizeMetrics, "x_ppem", ft_size_metrics_x_ppem, 0);
3119
+ rb_define_method(cSizeMetrics, "y_ppem", ft_size_metrics_y_ppem, 0);
3120
+ rb_define_method(cSizeMetrics, "x_scale", ft_size_metrics_x_scale, 0);
3121
+ rb_define_method(cSizeMetrics, "y_scale", ft_size_metrics_y_scale, 0);
3122
+
3123
+ /***************************/
3124
+ /* define FT2::Glyph class */
3125
+ /***************************/
3126
+ cGlyph = rb_define_class_under(mFt2, "Glyph", rb_cObject);
3127
+ rb_define_singleton_method(cGlyph, "initialize", ft_glyph_init, 0);
3128
+ rb_define_method(cGlyph, "library", ft_glyph_library, 0);
3129
+ rb_define_method(cGlyph, "class", ft_glyph_class, 0);
3130
+ rb_define_alias(cGlyph, "clazz", "class");
3131
+ rb_define_method(cGlyph, "format", ft_glyph_format, 0);
3132
+ rb_define_method(cGlyph, "advance", ft_glyph_advance, 0);
3133
+
3134
+ rb_define_method(cGlyph, "dup", ft_glyph_dup, 0);
3135
+ rb_define_alias(cGlyph, "copy", "dup");
3136
+
3137
+ rb_define_method(cGlyph, "transform", ft_glyph_transform, 2);
3138
+
3139
+ rb_define_method(cGlyph, "cbox", ft_glyph_cbox, 2);
3140
+ rb_define_alias(cGlyph, "control_box", "cbox");
3141
+
3142
+ rb_define_method(cGlyph, "to_bmap", ft_glyph_to_bmap, 3);
3143
+ rb_define_alias(cGlyph, "to_bitmap", "to_bmap");
3144
+
3145
+ /*********************************/
3146
+ /* define FT2::BitmapGlyph class */
3147
+ /*********************************/
3148
+ cBitmapGlyph = rb_define_class_under(mFt2, "BitmapGlyph", cGlyph);
3149
+ rb_define_singleton_method(cBitmapGlyph, "initialize", ft_bmapglyph_init, 0);
3150
+
3151
+ rb_define_method(cBitmapGlyph, "left", ft_bmapglyph_left, 0);
3152
+ rb_define_method(cBitmapGlyph, "top", ft_bmapglyph_top, 0);
3153
+ rb_define_method(cBitmapGlyph, "bitmap", ft_bmapglyph_bitmap, 0);
3154
+
3155
+ /*********************************/
3156
+ /* define FT2::OutlineGlyph class */
3157
+ /*********************************/
3158
+ cOutlineGlyph = rb_define_class_under(mFt2, "OutlineGlyph", cGlyph);
3159
+ rb_define_singleton_method(cOutlineGlyph, "initialize", ft_outlineglyph_init, 0);
3160
+
3161
+ /********************************/
3162
+ /* define FT2::GlyphClass class */
3163
+ /********************************/
3164
+ cGlyphClass = rb_define_class_under(mFt2, "GlyphClass", rb_cObject);
3165
+
3166
+ /******************************/
3167
+ /* define FT2::SubGlyph class */
3168
+ /******************************/
3169
+ cSubGlyph = rb_define_class_under(mFt2, "SubGlyph", rb_cObject);
3170
+ }