1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #include <sys/types.h>
35 #include "m17n-misc.h"
39 #include "internal-gui.h"
45 #include <freetype/ftbdf.h>
47 #ifdef HAVE_FONTCONFIG
48 #include <fontconfig/fontconfig.h>
50 int fontconfig_initialized = 0;
52 #endif /* not HAVE_FONTCONFIG */
54 static MSymbol Municode_bmp, Municode_full, Miso10646_1, Miso8859_1;
56 static FT_Library ft_library;
61 MSymbol weight, style, stretch;
64 static int ft_to_prop_size;
65 static MFTtoProp *ft_to_prop;
67 /** List of FreeType fonts. Keys are family names, values are plists
68 contains fonts of the corresponding family. In the deeper plist,
69 keys are Mt, values are (MFTInfo *). */
70 static MPlist *ft_font_list;
72 static int all_fonts_scaned;
74 /** Return 0 if NAME implies TrueType or OpenType fonts. Othersize
78 check_otf_filename (const char *name)
80 int len = strlen (name);
81 const char *ext = name + (len - 4);
84 || (memcmp (ext, ".ttf", 4)
85 && memcmp (ext, ".TTF", 4)
86 && memcmp (ext, ".otf", 4)
87 && memcmp (ext, ".OTF", 4)))
92 /** Setup members of FT_INFO from FT_FACE. Return the family name. */
95 set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family)
97 MFont *font = &ft_info->font;
101 MPlist *charmap_list;
102 int unicode_bmp = -1, unicode_full = -1, unicode = -1;
109 len = strlen (ft_face->family_name) + 1;
110 buf = (char *) alloca (len);
111 memcpy (buf, ft_face->family_name, len);
112 for (p = buf; *p; p++)
113 if (*p >= 'A' && *p <= 'Z')
115 family = msymbol (buf);
117 mfont__set_property (font, MFONT_FAMILY, family);
119 if (ft_face->style_name)
121 len = strlen (ft_face->style_name) + 1;
122 buf = (char *) alloca (len);
123 memcpy (buf, ft_face->style_name, len);
124 for (p = buf; *p; p++)
125 if (*p >= 'A' && *p <= 'Z')
127 style = msymbol (buf);
128 for (i = 0; i < ft_to_prop_size; i++)
129 if (ft_to_prop[i].ft_style == style)
131 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
132 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
133 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
140 if (i == ft_to_prop_size)
142 mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium"));
143 mfont__set_property (font, MFONT_STYLE, msymbol ("r"));
144 mfont__set_property (font, MFONT_STRETCH, msymbol ("normal"));
147 mfont__set_property (font, MFONT_ADSTYLE, msymbol (""));
149 charmap_list = mplist ();
150 mplist_add (charmap_list, Mt, (void *) -1);
151 for (i = 0; i < ft_face->num_charmaps; i++)
153 char registry_buf[16];
156 sprintf (registry_buf, "%d-%d",
157 ft_face->charmaps[i]->platform_id,
158 ft_face->charmaps[i]->encoding_id);
159 registry = msymbol (registry_buf);
160 mplist_add (charmap_list, registry, (void *) i);
162 if (ft_face->charmaps[i]->platform_id == 0)
164 if (ft_face->charmaps[i]->encoding_id == 3)
166 else if (ft_face->charmaps[i]->encoding_id == 4)
169 else if (ft_face->charmaps[i]->platform_id == 3)
171 if (ft_face->charmaps[i]->encoding_id == 1)
173 else if (ft_face->charmaps[i]->encoding_id == 10)
176 else if (ft_face->charmaps[i]->platform_id == 1
177 && ft_face->charmaps[i]->encoding_id == 0)
178 mplist_add (charmap_list, msymbol ("apple-roman"), (void *) i);
180 if (unicode_full >= 0)
182 mplist_add (charmap_list, Municode_full, (void *) unicode_full);
183 mplist_add (charmap_list, Municode_bmp, (void *) unicode_full);
184 mplist_add (charmap_list, Miso10646_1, (void *) unicode_full);
185 unicode = unicode_full;
187 else if (unicode_bmp >= 0)
189 mplist_add (charmap_list, Municode_bmp, (void *) unicode_bmp);
190 mplist_add (charmap_list, Miso10646_1, (void *) unicode_bmp);
191 unicode = unicode_bmp;
195 FT_Set_Charmap (ft_face, ft_face->charmaps[unicode]);
196 for (i = 255; i >= 32; i--)
200 if (FT_Get_Char_Index (ft_face, (FT_ULong) i) == 0)
204 mplist_add (charmap_list, Miso8859_1, (void *) unicode);
207 ft_info->charmap_list = charmap_list;
209 if (! FT_IS_SCALABLE (ft_face))
211 BDF_PropertyRec prop;
213 FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop);
214 font->property[MFONT_SIZE] = prop.u.integer * 10;
215 FT_Get_BDF_Property (ft_face, "RESOLUTION_Y", &prop);
216 font->property[MFONT_RESY] = prop.u.integer;
224 close_ft (void *object)
226 MFTInfo *ft_info = object;
228 if (ft_info->ft_face)
230 if (ft_info->extra_info)
231 M17N_OBJECT_UNREF (ft_info->extra_info);
232 FT_Done_Face (ft_info->ft_face);
235 OTF_close (ft_info->otf);
236 #endif /* HAVE_OTF */
238 free (ft_info->filename);
239 M17N_OBJECT_UNREF (ft_info->charmap_list);
244 add_font_info (char *filename, MSymbol family)
247 BDF_PropertyRec prop;
248 MFTInfo *ft_info = NULL;
250 if (FT_New_Face (ft_library, filename, 0, &ft_face) == 0)
252 if (FT_IS_SCALABLE (ft_face)
253 || FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0)
258 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
259 ft_info->filename = strdup (filename);
260 ft_info->otf_flag = check_otf_filename (filename);
261 fam = set_font_info (ft_face, ft_info, family);
262 plist = mplist_get (ft_font_list, fam);
266 mplist_add (ft_font_list, fam, plist);
268 mplist_add (plist, fam, ft_info);
270 FT_Done_Face (ft_face);
274 #ifdef HAVE_FONTCONFIG
277 fc_list (MSymbol family)
291 fc_config = FcConfigGetCurrent ();
292 MPLIST_DO (plist, mfont_freetype_path)
293 if (MPLIST_STRING_P (plist)
294 && (pathname = MPLIST_STRING (plist))
295 && stat (pathname, &buf) == 0)
296 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
299 pattern = FcPatternCreate ();
301 FcPatternAddString (pattern, FC_FAMILY,
302 (FcChar8 *) (msymbol_name (family)));
303 os = FcObjectSetBuild (FC_FILE, NULL);
304 fs = FcFontList (fc_config, pattern, os);
309 for (i = 0; i < fs->nfont; i++)
311 FcPatternGetString (fs->fonts[i], FC_FILE, 0, (FcChar8 **) &filename);
312 add_font_info (filename, family);
314 FcFontSetDestroy (fs);
316 FcObjectSetDestroy (os);
317 FcPatternDestroy (pattern);
320 #else /* not HAVE_FONTCONFIG */
329 MPLIST_DO (plist, mfont_freetype_path)
330 if (MPLIST_STRING_P (plist)
331 && (pathname = MPLIST_STRING (plist))
332 && stat (pathname, &buf) == 0)
334 if (S_ISREG (buf.st_mode))
335 add_font_info (pathname, Mnil);
336 else if (S_ISDIR (buf.st_mode))
338 int len = strlen (pathname);
340 DIR *dir = opendir (pathname);
345 strcpy (path, pathname);
346 strcpy (path + len, "/");
348 while ((dp = readdir (dir)) != NULL)
350 strcpy (path + len, dp->d_name);
351 add_font_info (path, Mnil);
359 #endif /* not HAVE_FONTCONFIG */
361 /* The FreeType font driver function SELECT. */
363 static MRealizedFont *
364 ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
369 MRealizedFont *rfont;
370 MSymbol family, registry;
374 family = FONT_PROPERTY (spec, MFONT_FAMILY);
376 family = FONT_PROPERTY (request, MFONT_FAMILY);
377 registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
378 if (registry == Mnil)
382 ft_font_list = mplist ();
383 #ifdef HAVE_FONTCONFIG
386 plist = mplist_get (ft_font_list, family);
390 plist = mplist_get (ft_font_list, family);
393 mplist_add (ft_font_list, family, plist = mplist ());
400 if (! all_fonts_scaned)
403 all_fonts_scaned = 1;
406 #else /* not HAVE_FONTCONFIG */
407 if (! all_fonts_scaned)
410 all_fonts_scaned = 1;
414 plist = mplist_get (ft_font_list, family);
418 #endif /* not HAVE_FONTCONFIG */
421 plist = MPLIST_VAL (ft_font_list);
424 MPLIST_DO (pl, plist)
426 MFTInfo *ft_info = MPLIST_VAL (pl);
429 if (! mplist_find_by_key (ft_info->charmap_list, registry))
431 /* We always ignore FOUNDRY. */
432 ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY];
433 score = mfont__score (&ft_info->font, spec, request, limited_size);
436 || best_score > score))
446 plist = MPLIST_NEXT (plist);
447 if (! MPLIST_TAIL_P (plist))
453 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
454 rfont->frame = frame;
456 rfont->request = *request;
457 rfont->font = best_font->font;
458 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
459 rfont->font.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
460 rfont->score = best_score;
461 rfont->info = best_font;
462 M17N_OBJECT_REF (best_font);
467 /* The FreeType font driver function OPEN. */
470 ft_open (MRealizedFont *rfont)
472 MFTInfo *base = rfont->info, *ft_info;
473 MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
474 int mdebug_mask = MDEBUG_FONT;
477 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
478 ft_info->font = base->font;
479 ft_info->filename = strdup (base->filename);
480 ft_info->otf_flag = base->otf_flag;
481 ft_info->charmap_list = base->charmap_list;
482 M17N_OBJECT_REF (ft_info->charmap_list);
483 M17N_OBJECT_UNREF (base);
484 rfont->info = ft_info;
487 ft_info->ft_face = NULL;
488 if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face))
490 if (registry == Mnil)
492 ft_info->charmap_index
493 = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry);
494 if (ft_info->charmap_index >= 0
495 && FT_Set_Charmap (ft_info->ft_face,
496 ft_info->ft_face->charmaps[ft_info->charmap_index]))
498 size = rfont->font.property[MFONT_SIZE] / 10;
499 if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size))
502 MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename);
504 rfont->ascent = ft_info->ft_face->ascender >> 6;
505 rfont->descent = - (ft_info->ft_face->descender >> 6);
509 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
510 if (ft_info->ft_face)
511 FT_Done_Face (ft_info->ft_face);
512 M17N_OBJECT_UNREF (ft_info->charmap_list);
513 free (ft_info->filename);
519 /* The FreeType font driver function FIND_METRIC. */
522 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
525 MFTInfo *ft_info = (MFTInfo *) rfont->info;
526 FT_Face ft_face = ft_info->ft_face;
527 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
529 for (; g != gend; g++)
531 if (g->code == MCHAR_INVALID_CODE)
533 if (FT_IS_SCALABLE (ft_face))
535 unsigned unitsPerEm = ft_face->units_per_EM;
536 int size = rfont->font.property[MFONT_SIZE] / 10;
539 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
540 g->width = ft_face->max_advance_width * size / unitsPerEm;
541 g->ascent = ft_face->ascender * size / unitsPerEm;
542 g->descent = (- ft_face->descender) * size / unitsPerEm;
546 BDF_PropertyRec prop;
549 g->rbearing = g->width = ft_face->available_sizes->width;
550 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
552 g->ascent = prop.u.integer;
553 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
554 g->descent = prop.u.integer;
558 g->ascent = ft_face->available_sizes->height;
565 FT_Glyph_Metrics *metrics;
567 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_DEFAULT);
568 metrics = &ft_face->glyph->metrics;
569 g->lbearing = (metrics->horiBearingX >> 6);
570 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
571 g->width = metrics->horiAdvance >> 6;
572 g->ascent = metrics->horiBearingY >> 6;
573 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
578 /* The FreeType font driver function ENCODE_CHAR. */
581 ft_encode_char (MRealizedFont *rfont, unsigned code)
585 if (rfont->status == 0)
587 if ((rfont->driver->open) (rfont) < 0)
590 ft_info = (MFTInfo *) rfont->info;
591 code = (unsigned) FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) code);
593 return MCHAR_INVALID_CODE;
598 /* The FreeType font driver function RENDER. */
600 #define NUM_POINTS 0x1000
603 MDrawPoint points[NUM_POINTS];
608 ft_render (MDrawWindow win, int x, int y,
609 MGlyphString *gstring, MGlyph *from, MGlyph *to,
610 int reverse, MDrawRegion region)
614 MRealizedFace *rface = from->rface;
615 MFrame *frame = rface->frame;
616 FT_Int32 load_flags = FT_LOAD_RENDER;
619 MPointTable point_table[8];
624 /* It is assured that the all glyphs in the current range use the
625 same realized face. */
626 ft_info = (MFTInfo *) rface->rfont->info;
627 ft_face = ft_info->ft_face;
629 if (! gstring->anti_alias)
631 #ifdef FT_LOAD_TARGET_MONO
632 load_flags |= FT_LOAD_TARGET_MONO;
634 load_flags |= FT_LOAD_MONOCHROME;
638 for (i = 0; i < 8; i++)
639 point_table[i].p = point_table[i].points;
641 for (g = from; g < to; x += g++->width)
649 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
650 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
651 bmp = ft_face->glyph->bitmap.buffer;
652 width = ft_face->glyph->bitmap.width;
653 pitch = ft_face->glyph->bitmap.pitch;
654 if (! gstring->anti_alias)
659 if (gstring->anti_alias)
660 for (i = 0; i < ft_face->glyph->bitmap.rows;
661 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
663 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
664 for (j = 0; j < width; j++, xoff++)
666 intensity = bmp[j] >> 5;
669 ptable = point_table + intensity;
673 if (ptable->p - ptable->points == NUM_POINTS)
675 (*frame->driver->draw_points)
677 reverse ? 7 - intensity : intensity,
678 ptable->points, NUM_POINTS, region);
679 ptable->p = ptable->points;
685 for (i = 0; i < ft_face->glyph->bitmap.rows;
686 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
688 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
689 for (j = 0; j < width; j++, xoff++)
691 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
694 ptable = point_table;
698 if (ptable->p - ptable->points == NUM_POINTS)
700 (*frame->driver->draw_points) (frame, win, rface,
702 ptable->points, NUM_POINTS, region);
703 ptable->p = ptable->points;
710 if (gstring->anti_alias)
712 for (i = 1; i < 8; i++)
713 if (point_table[i].p != point_table[i].points)
714 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
715 point_table[i].points,
716 point_table[i].p - point_table[i].points, region);
720 if (point_table[0].p != point_table[0].points)
721 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
722 point_table[0].points,
723 point_table[0].p - point_table[0].points, region);
730 MFontDriver mfont__ft_driver =
731 { ft_select, ft_open, ft_find_metric, ft_encode_char, ft_render };
738 char *weight, *style, *stretch;
739 } ft_to_prop_name[] =
740 { { "regular", "medium", "r", "normal" },
741 { "medium", "medium", "r", "normal" },
742 { "normal", "medium", "r", "normal" },
743 { "italic", "medium", "i", "normal" },
744 { "bold", "bold", "r", "normal" },
745 { "bolditalic", "bold", "i", "normal" },
746 { "bold italic", "bold", "i", "normal" },
747 { "narrow", "medium", "r", "condensed" },
748 { "narrow italic", "medium", "i", "condensed" },
749 { "narrow bold", "bold", "r", "condensed" },
750 { "narrow bold italic", "bold", "i", "condensed" },
751 { "black", "black", "r", "normal" },
752 { "black italic", "black", "i", "normal" },
753 { "oblique", "medium", "o", "normal" },
754 { "boldoblique", "bold", "o", "normal" },
755 { "bold oblique", "bold", "o", "normal" } };
758 if (FT_Init_FreeType (&ft_library) != 0)
759 MERROR (MERROR_FONT_FT, -1);
761 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
762 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
763 for (i = 0; i < ft_to_prop_size; i++)
765 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
766 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
767 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
768 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
771 Municode_bmp = msymbol ("unicode-bmp");
772 Municode_full = msymbol ("unicode-full");
773 Miso10646_1 = msymbol ("iso10646-1");
774 Miso8859_1 = msymbol ("iso8859-1");
786 MPLIST_DO (plist, ft_font_list)
788 MPLIST_DO (p, MPLIST_VAL (plist))
790 MFTInfo *ft_info = MPLIST_VAL (p);
792 M17N_OBJECT_UNREF (ft_info);
794 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
796 M17N_OBJECT_UNREF (ft_font_list);
800 FT_Done_FreeType (ft_library);
801 all_fonts_scaned = 0;
805 #ifdef HAVE_FONTCONFIG
807 mfont__ft_parse_name (char *name, MFont *font)
809 FcPattern *pat = FcNameParse ((FcChar8 *) name);
816 if ((result = FcPatternGetString (pat, FC_FOUNDRY, 0, &str)) == FcResultMatch)
817 mfont__set_property (font, MFONT_FOUNDRY, msymbol ((char *) str));
818 if ((result = FcPatternGetString (pat, FC_FAMILY, 0, &str)) == FcResultMatch)
819 mfont__set_property (font, MFONT_FAMILY, msymbol ((char *) str));
820 if ((result = FcPatternGetString (pat, FC_STYLE, 0, &str)) == FcResultMatch)
822 MSymbol style = msymbol ((char *) str);
825 for (i = 0; i < ft_to_prop_size; i++)
826 if (ft_to_prop[i].ft_style == style)
828 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
829 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
830 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
834 if ((result = FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size))
836 font->property[MFONT_SIZE] = size * 10;
837 FcPatternDestroy (pat);
842 mfont__ft_unparse_name (MFont *font)
844 FcPattern *pat = FcPatternCreate ();
845 MSymbol sym, weight, style, stretch;
849 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
850 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
851 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
852 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
853 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) == Mnil)
854 weight = msymbol ("medium");
855 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) == Mnil)
856 style = msymbol ("r");
857 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) == Mnil)
858 stretch = msymbol ("normal");
859 for (i = 0; i < ft_to_prop_size; i++)
860 if (ft_to_prop[i].weight == weight
861 && ft_to_prop[i].style == style
862 && ft_to_prop[i].stretch == stretch)
863 FcPatternAddString (pat, FC_STYLE,
864 (FcChar8 *) MSYMBOL_NAME (ft_to_prop[i].ft_style));
865 name = (char *) FcNameUnparse (pat);
866 FcPatternDestroy (pat);
869 #endif /* HAVE_FONTCONFIG */
874 #define DEVICE_DELTA(table, size) \
875 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
876 ? (table).DeltaValue[(size) >= (table).StartSize] \
880 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
881 unsigned code, int size, int *x, int *y)
883 if (anchor->AnchorFormat == 2)
886 int ap = anchor->f.f1.AnchorPoint;
888 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
889 outline = &ft_face->glyph->outline;
890 if (ap < outline->n_points)
892 *x = outline->points[ap].x;
893 *y = outline->points[ap].y;
896 else if (anchor->AnchorFormat == 3)
898 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
899 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
904 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
905 MSymbol script, MSymbol langsys,
906 MSymbol gsub_features, MSymbol gpos_features)
909 MGlyph *g = MGLYPH (from);
911 MRealizedFont *rfont;
914 OTF_GlyphString otf_gstring;
916 char *script_name, *language_name;
917 char *gsub_feature_names, *gpos_feature_names;
923 rfont = g->rface->rfont;
924 ft_info = rfont->info;
925 if (ft_info->otf_flag < 0)
930 otf = OTF_open (ft_info->filename);
931 if (otf && OTF_get_table (otf, "head") < 0)
938 ft_info->otf_flag = -1;
945 script_name = msymbol_name (script);
949 language_name = msymbol_name (langsys);
951 language_name = NULL;
953 = (gsub_features == Mt ? "*"
954 : gsub_features == Mnil ? NULL
955 : msymbol_name (gsub_features));
956 if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0)
957 gsub_feature_names = NULL;
959 = (gpos_features == Mt ? "*"
960 : gpos_features == Mnil ? NULL
961 : msymbol_name (gpos_features));
962 if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0)
963 gpos_feature_names = NULL;
965 otf_gstring.size = otf_gstring.used = len;
966 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
967 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
968 for (i = 0, need_cmap = 0; i < len; i++)
970 if (gstring->glyphs[from + i].otf_encoded)
972 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
973 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
977 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
982 && OTF_drive_cmap (otf, &otf_gstring) < 0)
985 OTF_drive_gdef (otf, &otf_gstring);
986 gidx = gstring->used;
988 if (gsub_feature_names)
990 if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name,
991 gsub_feature_names) < 0)
993 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
995 MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
998 temp.combining_code = 0;
1001 temp.code = otfg->glyph_id;
1002 temp.otf_encoded = 1;
1007 temp.otf_encoded = 0;
1009 temp.to = MGLYPH (from + otfg->f.index.to)->to;
1010 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1014 for (i = 0; i < len; i++)
1016 MGlyph temp = gstring->glyphs[from + i];
1018 if (otf_gstring.glyphs[i].glyph_id)
1020 temp.code = otf_gstring.glyphs[i].glyph_id;
1021 temp.otf_encoded = 1;
1023 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1026 ft_find_metric (rfont, gstring, gidx, gstring->used);
1028 if (gpos_feature_names)
1032 MGlyph *base = NULL, *mark = NULL;
1034 if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name,
1035 gpos_feature_names) < 0)
1038 u = otf->head->unitsPerEm;
1039 size10 = rfont->font.property[MFONT_SIZE];
1042 for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
1043 i < otf_gstring.used; i++, otfg++, g++)
1047 if (! otfg->glyph_id)
1049 switch (otfg->positioning_type)
1055 int format = otfg->f.f1.format;
1057 if (format & OTF_XPlacement)
1058 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
1059 if (format & OTF_XPlaDevice)
1060 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
1061 if (format & OTF_YPlacement)
1062 g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
1063 if (format & OTF_YPlaDevice)
1064 g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
1065 if (format & OTF_XAdvance)
1066 g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
1067 if (format & OTF_XAdvDevice)
1068 g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
1072 /* Not yet supported. */
1078 goto label_adjust_anchor;
1079 default: /* i.e. case 6 */
1084 label_adjust_anchor:
1086 int base_x, base_y, mark_x, mark_y;
1088 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
1089 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
1090 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
1091 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
1093 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1094 adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face,
1095 prev->code, size, &base_x, &base_y);
1096 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1097 adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face,
1098 g->code, size, &mark_x, &mark_y);
1099 g->xoff = prev->xoff + (base_x - prev->width) - mark_x;
1100 g->yoff = prev->yoff + mark_y - base_y;
1101 g->combining_code = MAKE_COMBINING_CODE_BY_CLASS (0);
1104 if (otfg->GlyphClass == OTF_GlyphClass0)
1106 else if (otfg->GlyphClass == OTF_GlyphClassMark)
1115 ft_find_metric (rfont, gstring, from, to);
1116 for (i = 0; i < len; i++)
1118 MGlyph temp = gstring->glyphs[from + i];
1119 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1126 mfont__ft_decode_otf (MGlyph *g)
1128 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1129 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1131 return (c ? c : -1);
1134 #endif /* HAVE_OTF */
1136 #endif /* HAVE_FREETYPE */