1
/***********************************************************************/
5
/* Jun Furuse, projet Cristal, INRIA Rocquencourt */
7
/* Copyright 1999,2000 */
8
/* Institut National de Recherche en Informatique et en Automatique. */
9
/* Distributed only by permission. */
11
/***********************************************************************/
15
#include <caml/mlvalues.h>
16
#include <caml/alloc.h>
17
#include <caml/memory.h>
18
#include <caml/callback.h>
19
#include <caml/fail.h>
21
#if (HAVE_FREETYPE && HAVE_FREETYPE2)
24
#include FT_FREETYPE_H
31
if( (library = stat_alloc( sizeof(FT_Library) )) == NULL ){
32
failwith( "init_FreeType: Memory over" );
34
if( FT_Init_FreeType( library ) ){
35
failwith( "FT_Init_FreeType" );
37
CAMLreturn( (value) library );
40
value done_FreeType( library )
44
if ( FT_Done_FreeType( *(FT_Library *)library ) ){
45
failwith( "FT_Done_FreeType" );
47
stat_free( (void *) library );
52
value new_Face( library, fontpath, idx )
57
CAMLparam3(library, fontpath, idx );
60
if( (face = stat_alloc( sizeof(FT_Face) )) == NULL ){
61
failwith( "new_Face: Memory over" );
63
if( FT_New_Face( *(FT_Library *)library, String_val( fontpath ), Int_val( idx ), face ) ){
64
failwith( "new_Face: Could not open face" );
66
CAMLreturn( (value) face );
69
value face_info( facev )
75
FT_Face face = *(FT_Face *)facev;
76
res = alloc_tuple(14);
77
Store_field(res, 0, Val_int( face->num_faces ));
78
Store_field(res, 1, Val_int( face->num_glyphs ));
79
Store_field(res, 2, copy_string( face->family_name == NULL ? "" : face->family_name ));
80
Store_field(res, 3, copy_string( face->style_name == NULL ? "" : face->style_name ));
81
Store_field(res, 4, Val_bool( FT_HAS_HORIZONTAL( face ) ));
82
Store_field(res, 5, Val_bool( FT_HAS_VERTICAL( face ) ));
83
Store_field(res, 6, Val_bool( FT_HAS_KERNING( face ) ));
84
Store_field(res, 7, Val_bool( FT_IS_SCALABLE( face ) ));
85
Store_field(res, 8, Val_bool( FT_IS_SFNT( face ) ));
86
Store_field(res, 9, Val_bool( FT_IS_FIXED_WIDTH( face ) ));
87
Store_field(res,10, Val_bool( FT_HAS_FIXED_SIZES( face ) ));
88
Store_field(res,11, Val_bool( FT_HAS_FAST_GLYPHS( face ) ));
89
Store_field(res,12, Val_bool( FT_HAS_GLYPH_NAMES( face ) ));
90
Store_field(res,13, Val_bool( FT_HAS_MULTIPLE_MASTERS( face ) ));
95
value done_Face( face )
99
if ( FT_Done_Face( *(FT_Face *) face ) ){
100
failwith("FT_Done_Face");
102
CAMLreturn( Val_unit );
105
value get_num_glyphs( face )
109
CAMLreturn( Val_int ((*(FT_Face *) face)->num_glyphs) );
113
value set_Char_Size( face, char_w, char_h, res_h, res_v )
115
value char_w, char_h; /* 26.6 1 = 1/64pt */
116
value res_h, res_v; /* dpi */
118
CAMLparam5( face, char_w, char_h, res_h, res_v );
119
if ( FT_Set_Char_Size( *(FT_Face *) face,
120
Int_val(char_w), Int_val(char_h),
121
Int_val(res_h), Int_val(res_v) ) ){
122
failwith("FT_Set_Char_Size");
124
CAMLreturn(Val_unit);
127
/* to be done: query at face->fixed_sizes
130
value set_Pixel_Sizes( face, pixel_w, pixel_h )
132
value pixel_w, pixel_h; /* dot */
134
CAMLparam3(face,pixel_w,pixel_h);
135
if ( FT_Set_Pixel_Sizes( *(FT_Face *) face,
136
Int_val(pixel_w), Int_val(pixel_h) ) ){
137
failwith("FT_Set_Pixel_Sizes");
139
CAMLreturn(Val_unit);
142
value val_CharMap( charmapp )
143
FT_CharMap *charmapp;
148
res = alloc_tuple(2);
149
Store_field(res,0, Val_int((*charmapp)->platform_id));
150
Store_field(res,1, Val_int((*charmapp)->encoding_id));
155
value get_CharMaps( facev )
159
CAMLlocal3(list,last_cell,new_cell);
163
face = *(FT_Face *) facev;
165
list = last_cell = Val_unit;
167
while( i < face->num_charmaps ){
168
new_cell = alloc_tuple(2);
169
Store_field(new_cell,0, val_CharMap( face->charmaps + i ));
170
Store_field(new_cell,1, Val_unit);
174
Store_field(last_cell,1, new_cell);
176
last_cell = new_cell;
183
value set_CharMap( facev, charmapv )
187
CAMLparam2(facev,charmapv);
193
face = *(FT_Face *) facev;
194
my_pid = Int_val(Field(charmapv, 0));
195
my_eid = Int_val(Field(charmapv, 1));
197
while( i < face->num_charmaps ){
198
charmap = face->charmaps[i];
199
if ( charmap->platform_id == my_pid &&
200
charmap->encoding_id == my_eid ){
201
if ( FT_Set_Charmap( face, charmap ) ){
202
failwith("FT_Set_Charmap");
204
CAMLreturn(Val_unit);
209
failwith("freetype:set_charmaps: selected pid+eid do not exist");
212
value get_Char_Index( face, code )
215
CAMLparam2(face,code);
216
CAMLreturn(Val_int(FT_Get_Char_Index( *(FT_Face *)face, Int_val(code))));
219
value load_Glyph( face, index, flags )
220
value face, index, flags;
222
CAMLparam3(face,index,flags);
225
if( FT_Load_Glyph( *(FT_Face *) face, Int_val(index), FT_LOAD_DEFAULT | Int_val(flags)) ){
226
failwith("FT_Load_Glyph");
229
res = alloc_tuple(2);
230
Store_field(res,0, Val_int( (*(FT_Face*)face)->glyph->advance.x ));
231
Store_field(res,1, Val_int( (*(FT_Face*)face)->glyph->advance.y ));
236
value load_Char( face, code, flags )
237
value face, code, flags;
239
CAMLparam3(face,code,flags);
242
/* FT_Load_Glyph(face, FT_Get_Char_Index( face, code )) */
243
if( FT_Load_Char( *(FT_Face *) face, Int_val(code), FT_LOAD_DEFAULT | Int_val(flags)) ){
244
failwith("FT_Load_Char");
247
res = alloc_tuple(2);
248
Store_field(res,0, Val_int( (*(FT_Face*)face)->glyph->advance.x ));
249
Store_field(res,1, Val_int( (*(FT_Face*)face)->glyph->advance.y ));
254
value render_Glyph_of_Face( face, mode )
258
CAMLparam2(face,mode);
259
if (FT_Render_Glyph( (*(FT_Face *)face)->glyph , Int_val(mode) )){
260
failwith("FT_Render_Glyph");
262
CAMLreturn(Val_unit);
265
value render_Char( face, code, flags, mode )
266
value face, code, flags, mode;
268
CAMLparam4(face,code,flags,mode);
271
/* FT_Load_Glyph(face, FT_Get_Char_Index( face, code ), FT_LOAD_RENDER) */
272
if( FT_Load_Char( *(FT_Face *) face, Int_val(code),
275
(Int_val(mode) ? FT_LOAD_MONOCHROME : 0)) ){
276
failwith("FT_Load_Char");
279
res = alloc_tuple(2);
280
Store_field(res,0, Val_int( (*(FT_Face*)face)->glyph->advance.x ));
281
Store_field(res,1, Val_int( (*(FT_Face*)face)->glyph->advance.y ));
286
value set_Transform( face, vmatrix, vpen )
287
value face, vmatrix, vpen;
289
CAMLparam3(face, vmatrix, vpen);
293
matrix.xx = (FT_Fixed)( Int_val(Field(vmatrix,0)) );
294
matrix.xy = (FT_Fixed)( Int_val(Field(vmatrix,1)) );
295
matrix.yx = (FT_Fixed)( Int_val(Field(vmatrix,2)) );
296
matrix.yy = (FT_Fixed)( Int_val(Field(vmatrix,3)) );
297
pen.x = (FT_Fixed)( Int_val(Field(vpen,0)) );
298
pen.y = (FT_Fixed)( Int_val(Field(vpen,1)) );
300
FT_Set_Transform( *(FT_Face *)face, &matrix, &pen );
302
CAMLreturn(Val_unit);
305
value get_Bitmap_Info( vface )
311
FT_GlyphSlot glyph = (*(FT_Face *)vface)->glyph;
312
FT_Bitmap bitmap = glyph->bitmap;
314
switch ( bitmap.pixel_mode ) {
315
case ft_pixel_mode_grays:
316
if ( bitmap.num_grays != 256 ){
317
failwith("get_Bitmap_Info: unknown num_grays");
320
case ft_pixel_mode_mono:
323
failwith("get_Bitmap_Info: unknown pixel mode");
326
res = alloc_tuple(5);
327
Store_field(res,0, Val_int(glyph->bitmap_left));
328
Store_field(res,1, Val_int(glyph->bitmap_top));
329
Store_field(res,2, Val_int(bitmap.width));
330
Store_field(res,3, Val_int(bitmap.rows));
335
value read_Bitmap( vface, vx, vy ) /* This "y" is in Y upwards convention */
338
/* no boundary check !!! */
340
CAMLparam3(vface, vx, vy);
342
FT_Bitmap bitmap = (*(FT_Face *)vface)->glyph->bitmap;
349
switch ( bitmap.pixel_mode ) {
350
case ft_pixel_mode_grays:
351
if (bitmap.pitch > 0){
352
row = bitmap.buffer + (bitmap.rows - 1 - y) * bitmap.pitch;
354
row = bitmap.buffer - y * bitmap.pitch;
356
CAMLreturn (Val_int(row[x]));
358
case ft_pixel_mode_mono:
359
if (bitmap.pitch > 0){
360
row = bitmap.buffer + (bitmap.rows - 1 - y) * bitmap.pitch;
362
row = bitmap.buffer - y * bitmap.pitch;
364
CAMLreturn (Val_int(row[x >> 3] & (128 >> (x & 7)) ? 255 : 0));
368
failwith("read_Bitmap: unknown pixel mode");
373
value get_Glyph_Metrics( face )
377
CAMLlocal3(res1,res2,res);
379
/* no soundness check ! */
380
FT_Glyph_Metrics *metrics = &((*(FT_Face *)face)->glyph->metrics);
382
res1 = alloc_tuple(3);
383
Store_field(res1,0, Val_int(metrics->horiBearingX));
384
Store_field(res1,1, Val_int(metrics->horiBearingY));
385
Store_field(res1,2, Val_int(metrics->horiAdvance));
387
res2 = alloc_tuple(3);
388
Store_field(res2,0, Val_int(metrics->vertBearingX));
389
Store_field(res2,1, Val_int(metrics->vertBearingY));
390
Store_field(res2,2, Val_int(metrics->vertAdvance));
392
res = alloc_tuple(4);
393
Store_field(res,0, Val_int(metrics->width));
394
Store_field(res,1, Val_int(metrics->height));
395
Store_field(res,2, res1);
396
Store_field(res,3, res2);
401
value get_Size_Metrics( face )
407
FT_Size_Metrics *imetrics = &((*(FT_Face*)face)->size->metrics);
409
res = alloc_tuple(4);
410
Store_field(res,0, Val_int(imetrics->x_ppem));
411
Store_field(res,1, Val_int(imetrics->y_ppem));
412
Store_field(res,2, Val_int(imetrics->x_scale));
413
Store_field(res,3, Val_int(imetrics->y_scale));
418
value get_Outline_Contents(value face) {
419
/* *****************************************************************
421
Concrete definitions of TT_Outline might vary from version to
424
This definition assumes freetype 2.0.1
426
( anyway, this function is wrong...)
428
***************************************************************** */
430
CAMLlocal5(points, tags, contours, res, tmp);
433
FT_Outline* outline = &((*(FT_Face *)face)->glyph->outline);
435
int n_contours = outline->n_contours;
436
int n_points = outline->n_points;
438
points = alloc_tuple(n_points);
439
tags = alloc_tuple(n_points);
440
contours = alloc_tuple(n_contours);
442
for( i=0; i<n_points; i++ ) {
443
FT_Vector* raw_points = outline->points;
444
char* raw_flags = outline->tags;
445
tmp = alloc_tuple(2);
446
/* caution: 26.6 fixed into 31 bit */
447
Store_field(tmp, 0, Val_int(raw_points[i].x));
448
Store_field(tmp, 1, Val_int(raw_points[i].y));
449
Store_field(points, i, tmp);
450
if ( raw_flags[i] & FT_Curve_Tag_On ) {
451
Store_field(tags, i, Val_int(0)); /* On point */
452
} else if ( raw_flags[i] & FT_Curve_Tag_Cubic ) {
453
Store_field(tags, i, Val_int(2)); /* Off point, cubic */
455
Store_field(tags, i, Val_int(1)); /* Off point, conic */
459
for( i=0; i<n_contours; i++ ) {
460
short* raw_contours = outline->contours;
461
Store_field(contours, i, Val_int(raw_contours[i]));
464
res = alloc_tuple(5);
465
Store_field(res, 0, Val_int(n_contours));
466
Store_field(res, 1, Val_int(n_points));
467
Store_field(res, 2, points);
468
Store_field(res, 3, tags);
469
Store_field(res, 4, contours);