4 freetyp2.c - font support via the FreeType library version 2.
8 if (!i_ft2_init()) { error }
10 font = i_ft2_new(name, index);
11 if (!i_ft2_setdpi(font, xdpi, ydpi)) { error }
12 if (!i_ft2_getdpi(font, &xdpi, &ydpi)) { error }
14 if (!i_ft2_settransform(font, matrix)) { error }
15 int bbox[BOUNDING_BOX_COUNT];
16 if (!i_ft2_bbox(font, cheight, cwidth, text, length, bbox, utf8)) { error }
19 if (!i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, length, align,
21 if (!i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, length,
27 Implements Imager font support using the FreeType2 library.
29 The FreeType2 library understands several font file types, including
30 Truetype, Type1 and Windows FNT.
40 #include FT_FREETYPE_H
41 #ifdef FT_MULTIPLE_MASTERS_H
42 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
44 #include FT_MULTIPLE_MASTERS_H
48 static void ft2_push_message(int code);
50 static FT_Library library;
53 =item i_ft2_init(void)
55 Initializes the Freetype 2 library.
57 Returns true on success, false on failure.
66 error = FT_Init_FreeType(&library);
68 ft2_push_message(error);
69 i_push_error(0, "Initializing Freetype2");
75 struct FT2_Fonthandle {
81 /* used to adjust so we can align the draw point to the top-left */
85 /* Multiple master data if any */
91 /* the following is used to select a "best" encoding */
92 static struct enc_score {
97 /* the selections here are fairly arbitrary
98 ideally we need to give the user a list of encodings available
99 and a mechanism to choose one */
100 { ft_encoding_unicode, 10 },
101 { ft_encoding_sjis, 8 },
102 { ft_encoding_gb2312, 8 },
103 { ft_encoding_big5, 8 },
104 { ft_encoding_wansung, 8 },
105 { ft_encoding_johab, 8 },
106 { ft_encoding_latin_2, 6 },
107 { ft_encoding_apple_roman, 6 },
108 { ft_encoding_adobe_standard, 6 },
109 { ft_encoding_adobe_expert, 6 },
113 =item i_ft2_new(char *name, int index)
115 Creates a new font object, from the file given by I<name>. I<index>
116 is the index of the font in a file with multiple fonts, where 0 is the
119 Return NULL on failure.
125 i_ft2_new(char *name, int index) {
127 FT2_Fonthandle *result;
130 FT_Encoding encoding;
133 mm_log((1, "i_ft2_new(name %p, index %d)\n", name, index));
136 error = FT_New_Face(library, name, index, &face);
138 ft2_push_message(error);
139 i_push_error(error, "Opening face");
140 mm_log((2, "error opening face '%s': %d\n", name, error));
144 encoding = face->num_charmaps ? face->charmaps[0]->encoding : ft_encoding_unicode;
146 for (i = 0; i < face->num_charmaps; ++i) {
147 FT_Encoding enc_entry = face->charmaps[i]->encoding;
148 mm_log((2, "i_ft2_new, encoding %lX platform %u encoding %u\n",
149 enc_entry, face->charmaps[i]->platform_id,
150 face->charmaps[i]->encoding_id));
151 for (j = 0; j < sizeof(enc_scores) / sizeof(*enc_scores); ++j) {
152 if (enc_scores[j].encoding == enc_entry && enc_scores[j].score > score) {
153 encoding = enc_entry;
154 score = enc_scores[j].score;
159 FT_Select_Charmap(face, encoding);
160 mm_log((2, "i_ft2_new, selected encoding %lX\n", encoding));
162 result = mymalloc(sizeof(FT2_Fonthandle));
164 result->xdpi = result->ydpi = 72;
165 result->encoding = encoding;
167 /* by default we disable hinting on a call to i_ft2_settransform()
168 if we don't do this, then the hinting can the untransformed text
169 to be a different size to the transformed text.
170 Obviously we have it initially enabled.
174 /* I originally forgot this: :/ */
175 /*i_ft2_settransform(result, matrix); */
176 result->matrix[0] = 1; result->matrix[1] = 0; result->matrix[2] = 0;
177 result->matrix[3] = 0; result->matrix[4] = 1; result->matrix[5] = 0;
181 FT_Multi_Master *mm = &result->mm;
184 if ((face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) != 0
185 && (error = FT_Get_Multi_Master(face, mm)) == 0) {
186 mm_log((2, "MM Font, %d axes, %d designs\n", mm->num_axis, mm->num_designs));
187 for (i = 0; i < mm->num_axis; ++i) {
188 mm_log((2, " axis %d name %s range %ld - %ld\n", i, mm->axis[i].name,
189 (long)(mm->axis[i].minimum), (long)(mm->axis[i].maximum)));
194 mm_log((2, "No multiple masters\n"));
204 =item i_ft2_destroy(FT2_Fonthandle *handle)
206 Destroys a font object, which must have been the return value of
212 i_ft2_destroy(FT2_Fonthandle *handle) {
213 FT_Done_Face(handle->face);
218 =item i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi)
220 Sets the resolution in dots per inch at which point sizes scaled, by
221 default xdpi and ydpi are 72, so that 1 point maps to 1 pixel.
223 Both xdpi and ydpi should be positive.
225 Return true on success.
230 i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi) {
232 if (xdpi > 0 && ydpi > 0) {
238 i_push_error(0, "resolutions must be positive");
244 =item i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi)
246 Retrieves the current horizontal and vertical resolutions at which
247 point sizes are scaled.
252 i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi) {
253 *xdpi = handle->xdpi;
254 *ydpi = handle->ydpi;
260 =item i_ft2_settransform(FT2_FontHandle *handle, double *matrix)
262 Sets a transormation matrix for output.
264 This should be a 2 x 3 matrix like:
266 matrix[0] matrix[1] matrix[2]
267 matrix[3] matrix[4] matrix[5]
272 i_ft2_settransform(FT2_Fonthandle *handle, double *matrix) {
277 m.xx = matrix[0] * 65536;
278 m.xy = matrix[1] * 65536;
279 v.x = matrix[2]; /* this could be pels of 26.6 fixed - not sure */
280 m.yx = matrix[3] * 65536;
281 m.yy = matrix[4] * 65536;
282 v.y = matrix[5]; /* see just above */
284 FT_Set_Transform(handle->face, &m, &v);
286 for (i = 0; i < 6; ++i)
287 handle->matrix[i] = matrix[i];
294 =item i_ft2_sethinting(FT2_Fonthandle *handle, int hinting)
296 If hinting is non-zero then glyph hinting is enabled, otherwise disabled.
298 i_ft2_settransform() disables hinting to prevent distortions in
299 gradual text transformations.
303 int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting) {
304 handle->hint = hinting;
309 =item i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, int len, int *bbox)
311 Retrieves bounding box information for the font at the given
312 character width and height. This ignores the transformation matrix.
314 Returns non-zero on success.
319 i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth,
320 char const *text, int len, int *bbox, int utf8) {
325 int ascent = 0, descent = 0;
326 int glyph_ascent, glyph_descent;
327 FT_Glyph_Metrics *gm;
329 int loadFlags = FT_LOAD_DEFAULT;
332 mm_log((1, "i_ft2_bbox(handle %p, cheight %f, cwidth %f, text %p, len %d, bbox %p)\n",
333 handle, cheight, cwidth, text, len, bbox));
335 error = FT_Set_Char_Size(handle->face, cwidth*64, cheight*64,
336 handle->xdpi, handle->ydpi);
338 ft2_push_message(error);
339 i_push_error(0, "setting size");
343 loadFlags |= FT_LOAD_NO_HINTING;
350 c = i_utf8_advance(&text, &len);
352 i_push_error(0, "invalid UTF8 character");
357 c = (unsigned char)*text++;
361 index = FT_Get_Char_Index(handle->face, c);
362 error = FT_Load_Glyph(handle->face, index, loadFlags);
364 ft2_push_message(error);
365 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
369 gm = &handle->face->glyph->metrics;
370 glyph_ascent = gm->horiBearingY / 64;
371 glyph_descent = glyph_ascent - gm->height/64;
373 start = gm->horiBearingX / 64;
374 /* handles -ve values properly */
375 ascent = glyph_ascent;
376 descent = glyph_descent;
380 if (glyph_ascent > ascent)
381 ascent = glyph_ascent;
382 if (glyph_descent < descent)
383 descent = glyph_descent;
385 width += gm->horiAdvance / 64;
389 handle the case where the right the of the character overlaps the
391 rightb = (gm->horiAdvance - gm->horiBearingX - gm->width)/64;
397 bbox[BBOX_NEG_WIDTH] = start;
398 bbox[BBOX_GLOBAL_DESCENT] = handle->face->size->metrics.descender / 64;
399 bbox[BBOX_POS_WIDTH] = width - rightb;
400 bbox[BBOX_GLOBAL_ASCENT] = handle->face->size->metrics.ascender / 64;
401 bbox[BBOX_DESCENT] = descent;
402 bbox[BBOX_ASCENT] = ascent;
403 bbox[BBOX_ADVANCE_WIDTH] = width;
405 return BBOX_ADVANCE_WIDTH + 1;
409 =item transform_box(FT2_FontHandle *handle, int bbox[4])
411 bbox contains coorinates of a the top-left and bottom-right of a bounding
412 box relative to a point.
414 This is then transformed and the values in bbox[4] are the top-left
415 and bottom-right of the new bounding box.
417 This is meant to provide the bounding box of a transformed character
418 box. The problem is that if the character was round and is rotated,
419 the real bounding box isn't going to be much different from the
420 original, but this function will return a _bigger_ bounding box. I
421 suppose I could work my way through the glyph outline, but that's
426 void ft2_transform_box(FT2_Fonthandle *handle, int bbox[4]) {
428 double *matrix = handle->matrix;
430 work[0] = matrix[0] * bbox[0] + matrix[1] * bbox[1];
431 work[1] = matrix[3] * bbox[0] + matrix[4] * bbox[1];
432 work[2] = matrix[0] * bbox[2] + matrix[1] * bbox[1];
433 work[3] = matrix[3] * bbox[2] + matrix[4] * bbox[1];
434 work[4] = matrix[0] * bbox[0] + matrix[1] * bbox[3];
435 work[5] = matrix[3] * bbox[0] + matrix[4] * bbox[3];
436 work[6] = matrix[0] * bbox[2] + matrix[1] * bbox[3];
437 work[7] = matrix[3] * bbox[2] + matrix[4] * bbox[3];
439 bbox[0] = floor(i_min(i_min(work[0], work[2]),i_min(work[4], work[6])));
440 bbox[1] = floor(i_min(i_min(work[1], work[3]),i_min(work[5], work[7])));
441 bbox[2] = ceil(i_max(i_max(work[0], work[2]),i_max(work[4], work[6])));
442 bbox[3] = ceil(i_max(i_max(work[1], work[3]),i_max(work[5], work[7])));
446 =item expand_bounds(int bbox[4], int bbox2[4])
448 Treating bbox[] and bbox2[] as 2 bounding boxes, produces a new
449 bounding box in bbox[] that encloses both.
453 static void expand_bounds(int bbox[4], int bbox2[4]) {
454 bbox[0] = i_min(bbox[0], bbox2[0]);
455 bbox[1] = i_min(bbox[1], bbox2[1]);
456 bbox[2] = i_max(bbox[2], bbox2[2]);
457 bbox[3] = i_max(bbox[3], bbox2[3]);
461 =item i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, int len, int vlayout, int utf8, int *bbox)
463 Retrieves bounding box information for the font at the given
464 character width and height.
466 This version finds the rectangular bounding box of the glyphs, with
467 the text as transformed by the transformation matrix. As with
468 i_ft2_bbox (bbox[0], bbox[1]) will the the offset from the start of
469 the topline to the top-left of the bounding box. Unlike i_ft2_bbox()
470 this could be near the bottom left corner of the box.
472 (bbox[4], bbox[5]) is the offset to the start of the baseline.
473 (bbox[6], bbox[7]) is the offset from the start of the baseline to the
476 Returns non-zero on success.
481 i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth,
482 char const *text, int len, int vlayout, int utf8, int *bbox) {
487 int ascent = 0, descent = 0;
488 int glyph_ascent, glyph_descent;
489 FT_Glyph_Metrics *gm;
495 int loadFlags = FT_LOAD_DEFAULT;
498 loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
500 loadFlags |= FT_LOAD_NO_HINTING;
502 error = FT_Set_Char_Size(handle->face, cwidth*64, cheight*64,
503 handle->xdpi, handle->ydpi);
505 ft2_push_message(error);
506 i_push_error(0, "setting size");
514 c = i_utf8_advance(&text, &len);
516 i_push_error(0, "invalid UTF8 character");
521 c = (unsigned char)*text++;
525 index = FT_Get_Char_Index(handle->face, c);
526 error = FT_Load_Glyph(handle->face, index, loadFlags);
528 ft2_push_message(error);
529 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
533 slot = handle->face->glyph;
536 /* these probably don't mean much for vertical layouts */
537 glyph_ascent = gm->horiBearingY / 64;
538 glyph_descent = glyph_ascent - gm->height/64;
540 work[0] = gm->vertBearingX;
541 work[1] = gm->vertBearingY;
544 work[0] = gm->horiBearingX;
545 work[1] = gm->horiBearingY;
547 work[2] = gm->width + work[0];
548 work[3] = work[1] - gm->height;
550 bbox[4] = work[0] * handle->matrix[0] + work[1] * handle->matrix[1] + handle->matrix[2];
551 bbox[5] = work[0] * handle->matrix[3] + work[1] * handle->matrix[4] + handle->matrix[5];
552 bbox[4] = bbox[4] < 0 ? -(-bbox[4] + 32)/64 : (bbox[4] + 32) / 64;
555 ft2_transform_box(handle, work);
556 for (i = 0; i < 4; ++i)
563 for (i = 0; i < 4; ++i)
565 ascent = glyph_ascent;
566 descent = glyph_descent;
570 expand_bounds(bounds, work);
572 x += slot->advance.x / 64;
573 y += slot->advance.y / 64;
575 if (glyph_ascent > ascent)
576 ascent = glyph_ascent;
577 if (glyph_descent > descent)
578 descent = glyph_descent;
582 handle the case where the right the of the character overlaps the
584 /*int rightb = gm->horiAdvance - gm->horiBearingX - gm->width;
586 width -= rightb / 64;*/
590 /* at this point bounds contains the bounds relative to the CP,
591 and x, y hold the final position relative to the CP */
598 bbox[1] = -bounds[3];
600 bbox[3] = -bounds[1];
608 make_bmp_map(FT_Bitmap *bitmap, unsigned char *map);
611 =item i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, i_color *cl, double cheight, double cwidth, char *text, int len, int align, int aa)
613 Renders I<text> to (I<tx>, I<ty>) in I<im> using color I<cl> at the given
614 I<cheight> and I<cwidth>.
616 If align is 0, then the text is rendered with the top-left of the
617 first character at (I<tx>, I<ty>). If align is non-zero then the text
618 is rendered with (I<tx>, I<ty>) aligned with the base-line of the
621 If aa is non-zero then the text is anti-aliased.
623 Returns non-zero on success.
628 i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, i_color *cl,
629 double cheight, double cwidth, char const *text, int len, int align,
630 int aa, int vlayout, int utf8) {
633 FT_Glyph_Metrics *gm;
634 int bbox[BOUNDING_BOX_COUNT];
638 unsigned char map[256];
639 char last_mode = ft_pixel_mode_none;
643 int loadFlags = FT_LOAD_DEFAULT;
645 mm_log((1, "i_ft2_text(handle %p, im %p, tx %d, ty %d, cl %p, cheight %f, cwidth %f, text %p, len %d, align %d, aa %d)\n",
646 handle, im, tx, ty, cl, cheight, cwidth, text, align, aa));
649 if (!FT_HAS_VERTICAL(handle->face)) {
650 i_push_error(0, "face has no vertical metrics");
653 loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
656 loadFlags |= FT_LOAD_NO_HINTING;
658 /* set the base-line based on the string ascent */
659 if (!i_ft2_bbox(handle, cheight, cwidth, text, len, bbox, utf8))
663 /* this may need adjustment */
664 tx -= bbox[0] * handle->matrix[0] + bbox[5] * handle->matrix[1] + handle->matrix[2];
665 ty += bbox[0] * handle->matrix[3] + bbox[5] * handle->matrix[4] + handle->matrix[5];
670 c = i_utf8_advance(&text, &len);
672 i_push_error(0, "invalid UTF8 character");
677 c = (unsigned char)*text++;
681 index = FT_Get_Char_Index(handle->face, c);
682 error = FT_Load_Glyph(handle->face, index, loadFlags);
684 ft2_push_message(error);
685 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
689 slot = handle->face->glyph;
692 error = FT_Render_Glyph(slot, aa ? ft_render_mode_normal : ft_render_mode_mono);
694 ft2_push_message(error);
695 i_push_errorf(0, "rendering glyph 0x%04X (character \\x%02X)");
698 if (slot->bitmap.pixel_mode == ft_pixel_mode_mono) {
699 bmp = slot->bitmap.buffer;
700 for (y = 0; y < slot->bitmap.rows; ++y) {
703 for (x = 0; x < slot->bitmap.width; ++x) {
705 i_ppix(im, tx+x+slot->bitmap_left, ty+y-slot->bitmap_top, cl);
713 bmp += slot->bitmap.pitch;
717 /* grey scale or something we can treat as greyscale */
718 /* we create a map to convert from the bitmap values to 0-255 */
719 if (last_mode != slot->bitmap.pixel_mode
720 || last_grays != slot->bitmap.num_grays) {
721 if (!make_bmp_map(&slot->bitmap, map))
723 last_mode = slot->bitmap.pixel_mode;
724 last_grays = slot->bitmap.num_grays;
727 bmp = slot->bitmap.buffer;
728 for (y = 0; y < slot->bitmap.rows; ++y) {
729 for (x = 0; x < slot->bitmap.width; ++x) {
730 int value = map[bmp[x]];
732 i_gpix(im, tx+x+slot->bitmap_left, ty+y-slot->bitmap_top, &pel);
733 for (ch = 0; ch < im->channels; ++ch) {
735 ((255-value)*pel.channel[ch] + value * cl->channel[ch]) / 255;
737 i_ppix(im, tx+x+slot->bitmap_left, ty+y-slot->bitmap_top, &pel);
740 bmp += slot->bitmap.pitch;
744 tx += slot->advance.x / 64;
745 ty -= slot->advance.y / 64;
752 =item i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel, double cheight, double cwidth, char *text, int len, int align, int aa)
754 Renders I<text> to (I<tx>, I<ty>) in I<im> to I<channel> at the given
755 I<cheight> and I<cwidth>.
757 If align is 0, then the text is rendered with the top-left of the
758 first character at (I<tx>, I<ty>). If align is non-zero then the text
759 is rendered with (I<tx>, I<ty>) aligned with the base-line of the
762 If aa is non-zero then the text is anti-aliased.
764 Returns non-zero on success.
769 i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel,
770 double cheight, double cwidth, char const *text, int len, int align,
771 int aa, int vlayout, int utf8) {
777 mm_log((1, "i_ft2_cp(handle %p, im %p, tx %d, ty %d, channel %d, cheight %f, cwidth %f, text %p, len %d, ...)\n",
778 handle, im, tx, ty, channel, cheight, cwidth, text, len));
780 if (vlayout && !FT_HAS_VERTICAL(handle->face)) {
781 i_push_error(0, "face has no vertical metrics");
785 if (!i_ft2_bbox_r(handle, cheight, cwidth, text, len, vlayout, utf8, bbox))
788 work = i_img_empty_ch(NULL, bbox[2]-bbox[0]+1, bbox[3]-bbox[1]+1, 1);
790 if (!i_ft2_text(handle, work, -bbox[0], -bbox[1], &cl, cheight, cwidth,
791 text, len, 1, aa, vlayout, utf8))
799 /* render to the specified channel */
800 /* this will be sped up ... */
801 for (y = 0; y < work->ysize; ++y) {
802 for (x = 0; x < work->xsize; ++x) {
803 i_gpix(work, x, y, &cl);
804 i_gpix(im, tx + x + bbox[0], ty + y + bbox[1], &cl2);
805 cl2.channel[channel] = cl.channel[0];
806 i_ppix(im, tx + x + bbox[0], ty + y + bbox[1], &cl2);
814 =item i_ft2_has_chars(handle, char *text, int len, int utf8, char *out)
816 Check if the given characters are defined by the font.
818 Returns the number of characters that were checked.
822 int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, int len,
823 int utf8, char *out) {
825 mm_log((1, "i_ft2_has_chars(handle %p, text %p, len %d, utf8 %d)\n",
826 handle, text, len, utf8));
832 c = i_utf8_advance(&text, &len);
834 i_push_error(0, "invalid UTF8 character");
839 c = (unsigned char)*text++;
843 index = FT_Get_Char_Index(handle->face, c);
851 /* uses a method described in fterrors.h to build an error translation
854 #undef __FTERRORS_H__
855 #define FT_ERRORDEF(e, v, s) case v: i_push_error(code, s); return;
856 #define FT_ERROR_START_LIST
857 #define FT_ERROR_END_LIST
862 =head2 Internal Functions
864 These functions are used in the implementation of freetyp2.c and should not
865 (usually cannot) be called from outside it.
869 =item ft2_push_message(int code)
871 Pushes an error message corresponding to code onto the error stack.
875 static void ft2_push_message(int code) {
882 sprintf(unknown, "Unknown Freetype2 error code 0x%04X\n", code);
883 i_push_error(code, unknown);
887 =item make_bmp_map(FT_Bitmap *bitmap, unsigned char *map)
889 Creates a map to convert grey levels from the glyphs bitmap into
890 values scaled 0..255.
895 make_bmp_map(FT_Bitmap *bitmap, unsigned char *map) {
899 switch (bitmap->pixel_mode) {
900 case ft_pixel_mode_grays:
901 scale = bitmap->num_grays;
905 i_push_errorf(0, "I can't handle pixel mode %d", bitmap->pixel_mode);
909 /* build the table */
910 for (i = 0; i < scale; ++i)
911 map[i] = i * 255 / (bitmap->num_grays - 1);
916 /* FREETYPE_PATCH was introduced in 2.0.6, we don't want a false
917 positive on 2.0.0 to 2.0.4, so we accept a false negative in 2.0.5 */
918 #ifndef FREETYPE_PATCH
919 #define FREETYPE_PATCH 4
922 /* FT_Get_Postscript_Name() was introduced in FT2.0.5 */
923 #define IM_HAS_FACE_NAME (FREETYPE_MINOR > 0 || FREETYPE_PATCH >= 5)
924 /* #define IM_HAS_FACE_NAME 0 */
927 =item i_ft2_face_name(handle, name_buf, name_buf_size)
929 Fills the given buffer with the Postscript Face name of the font,
936 i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
938 char const *name = FT_Get_Postscript_Name(handle->face);
943 strncpy(name_buf, name, name_buf_size);
944 name_buf[name_buf_size-1] = '\0';
946 return strlen(name) + 1;
949 i_push_error(0, "no face name available");
956 i_push_error(0, "Freetype 2.0.6 or later required");
964 i_ft2_can_face_name(void) {
965 return IM_HAS_FACE_NAME;
968 /* FT_Has_PS_Glyph_Names() was introduced in FT2.1.1 */
969 /* well, I assume FREETYPE_MAJOR is 2, since we're here */
970 #if FREETYPE_MINOR < 1 || (FREETYPE_MINOR == 1 && FREETYPE_PATCH < 1)
971 #define FT_Has_PS_Glyph_Names(face) (FT_HAS_GLYPH_NAMES(face))
975 i_ft2_glyph_name(FT2_Fonthandle *handle, unsigned long ch, char *name_buf,
976 size_t name_buf_size, int reliable_only) {
977 #ifdef FT_CONFIG_OPTION_NO_GLYPH_NAMES
980 i_push_error(0, "FT2 configured without glyph name support");
988 if (!FT_HAS_GLYPH_NAMES(handle->face)) {
989 i_push_error(0, "no glyph names in font");
993 if (reliable_only && !FT_Has_PS_Glyph_Names(handle->face)) {
994 i_push_error(0, "no reliable glyph names in font - set reliable_only to 0 to try anyway");
999 index = FT_Get_Char_Index(handle->face, ch);
1002 FT_Error error = FT_Get_Glyph_Name(handle->face, index, name_buf,
1005 ft2_push_message(error);
1010 return strlen(name_buf) + 1;
1017 i_push_error(0, "no glyph for that character");
1025 i_ft2_can_do_glyph_names(void) {
1026 #ifdef FT_CONFIG_OPTION_NO_GLYPH_NAMES
1034 i_ft2_face_has_glyph_names(FT2_Fonthandle *handle) {
1035 #ifdef FT_CONFIG_OPTION_NO_GLYPH_NAMES
1038 return FT_Has_PS_Glyph_Names(handle->face);
1043 i_ft2_is_multiple_master(FT2_Fonthandle *handle) {
1046 return handle->has_mm;
1053 i_ft2_get_multiple_masters(FT2_Fonthandle *handle, i_font_mm *mm) {
1056 FT_Multi_Master *mms = &handle->mm;
1059 if (!handle->has_mm) {
1060 i_push_error(0, "Font has no multiple masters");
1063 mm->num_axis = mms->num_axis;
1064 mm->num_designs = mms->num_designs;
1065 for (i = 0; i < mms->num_axis; ++i) {
1066 mm->axis[i].name = mms->axis[i].name;
1067 mm->axis[i].minimum = mms->axis[i].minimum;
1068 mm->axis[i].maximum = mms->axis[i].maximum;
1074 i_push_error(0, "Multiple master functions unavailable");
1080 i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, long *coords) {
1083 FT_Long ftcoords[T1_MAX_MM_AXIS];
1087 if (!handle->has_mm) {
1088 i_push_error(0, "Font has no multiple masters");
1091 if (coord_count != handle->mm.num_axis) {
1092 i_push_error(0, "Number of MM coords doesn't match MM axis count");
1095 for (i = 0; i < coord_count; ++i)
1096 ftcoords[i] = coords[i];
1098 error = FT_Set_MM_Design_Coordinates(handle->face, coord_count, ftcoords);
1100 ft2_push_message(error);
1107 i_push_error(0, "Multiple master functions unavailable");
1118 Tony Cook <tony@develop-help.com>, with a fair amount of help from
1119 reading the code in font.c.
1123 font.c, Imager::Font(3), Imager(3)
1125 http://www.freetype.org/