Update iso639-2 language coverage info, fix Georgian orthography to
[platform/upstream/fontconfig.git] / src / fcfreetype.c
1 /*
2  * $XFree86: xc/lib/fontconfig/src/fcfreetype.c,v 1.6 2002/07/06 23:47:43 keithp Exp $
3  *
4  * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Keith Packard not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  Keith Packard makes no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include "fcint.h"
29 #include <freetype/freetype.h>
30 #include <freetype/internal/ftobjs.h>
31 #include <freetype/tttables.h>
32
33 /*
34  * Keep Han languages separated by eliminating languages
35  * that the codePageRange bits says aren't supported
36  */
37
38 static const struct {
39     int             bit;
40     const FcChar8   *lang;
41 } FcCodePageRange[] = {
42     { 17,       (const FcChar8 *) "ja" },
43     { 18,       (const FcChar8 *) "zh-tw" },
44     { 19,       (const FcChar8 *) "ko" },
45     { 20,       (const FcChar8 *) "zh-cn" },
46 };
47
48 #define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
49
50 FcBool
51 FcFreeTypeIsExclusiveLang (const FcChar8  *lang)
52 {
53     int     i;
54
55     for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
56     {
57         if (FcLangCompare (lang, FcCodePageRange[i].lang) != FcLangDifferentLang)
58             return FcTrue;
59     }
60     return FcFalse;
61 }
62
63 FcPattern *
64 FcFreeTypeQuery (const FcChar8  *file,
65                  int            id,
66                  FcBlanks       *blanks,
67                  int            *count)
68 {
69     FT_Face         face;
70     FcPattern       *pat;
71     int             slant;
72     int             weight;
73     int             i;
74     FcCharSet       *cs;
75     FT_Library      ftLibrary;
76     const FcChar8   *family;
77     TT_OS2          *os2;
78     const FcChar8   *exclusiveLang = 0;
79
80     if (FT_Init_FreeType (&ftLibrary))
81         return 0;
82     
83     if (FT_New_Face (ftLibrary, (char *) file, id, &face))
84         goto bail;
85
86     *count = face->num_faces;
87
88     pat = FcPatternCreate ();
89     if (!pat)
90         goto bail0;
91
92     if (!FcPatternAddBool (pat, FC_OUTLINE,
93                            (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
94         goto bail1;
95
96     if (!FcPatternAddBool (pat, FC_SCALABLE,
97                            (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
98         goto bail1;
99
100
101     slant = FC_SLANT_ROMAN;
102     if (face->style_flags & FT_STYLE_FLAG_ITALIC)
103         slant = FC_SLANT_ITALIC;
104
105     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
106         goto bail1;
107
108     weight = FC_WEIGHT_MEDIUM;
109     if (face->style_flags & FT_STYLE_FLAG_BOLD)
110         weight = FC_WEIGHT_BOLD;
111
112     if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
113         goto bail1;
114
115     family = (FcChar8 *) face->family_name;
116     if (!family)
117     {
118         family = (FcChar8 *) strrchr ((char *) file, '/');
119         if (family)
120             family++;
121         else
122             family = file;
123     }
124     if (!FcPatternAddString (pat, FC_FAMILY, family))
125         goto bail1;
126
127     if (face->style_name)
128     {
129         if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
130             goto bail1;
131     }
132
133     if (!FcPatternAddString (pat, FC_FILE, file))
134         goto bail1;
135
136     if (!FcPatternAddInteger (pat, FC_INDEX, id))
137         goto bail1;
138
139     if (!FcPatternAddString (pat, FC_SOURCE, (FcChar8 *) "FreeType"))
140         goto bail1;
141
142 #if 1
143     if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
144         if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
145             goto bail1;
146 #endif
147
148     /*
149      * Get the OS/2 table and poke about
150      */
151     os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
152     if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
153     {
154         for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
155         {
156             FT_ULong    bits;
157             int         bit;
158             if (FcCodePageRange[i].bit < 32)
159             {
160                 bits = os2->ulCodePageRange1;
161                 bit = FcCodePageRange[i].bit;
162             }
163             else
164             {
165                 bits = os2->ulCodePageRange2;
166                 bit = FcCodePageRange[i].bit - 32;
167             }
168             if (bits & (1 << bit))
169             {
170                 /* 
171                  * If the font advertises support for multiple
172                  * "exclusive" languages, then include support
173                  * for any language found to have coverage
174                  */
175                 if (exclusiveLang)
176                 {
177                     exclusiveLang = 0;
178                     break;
179                 }
180                 exclusiveLang = FcCodePageRange[i].lang;
181             }
182         }
183     }
184
185     /*
186      * Compute the unicode coverage for the font
187      */
188     cs = FcFreeTypeCharSet (face, blanks);
189     if (!cs)
190         goto bail1;
191
192     /*
193      * Skip over PCF fonts that have no encoded characters; they're
194      * usually just Unicode fonts transcoded to some legacy encoding
195      */
196     if (FcCharSetCount (cs) == 0)
197     {
198         if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
199             goto bail2;
200     }
201
202     if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
203         goto bail2;
204
205     if (!FcFreeTypeSetLang (pat, cs, exclusiveLang))
206         goto bail2;
207
208     /*
209      * Drop our reference to the charset
210      */
211     FcCharSetDestroy (cs);
212     
213     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
214     {
215         for (i = 0; i < face->num_fixed_sizes; i++)
216             if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
217                                      (double) face->available_sizes[i].height))
218                 goto bail1;
219         if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
220             goto bail1;
221     }
222
223     FT_Done_Face (face);
224     FT_Done_FreeType (ftLibrary);
225     return pat;
226
227 bail2:
228     FcCharSetDestroy (cs);
229 bail1:
230     FcPatternDestroy (pat);
231 bail0:
232     FT_Done_Face (face);
233 bail:
234     FT_Done_FreeType (ftLibrary);
235     return 0;
236 }