xftxlfd.c revision c76ae52d
1/*
2 * $Id: xftxlfd.c,v 1.1.1.1 2008/07/30 02:49:11 mrg Exp $
3 *
4 * Copyright © 2000 Keith Packard
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 "xftint.h"
26
27static XftSymbolic XftXlfdWeights[] = {
28    {	"light",    FC_WEIGHT_LIGHT	},
29    {	"medium",   FC_WEIGHT_MEDIUM	},
30    {	"regular",  FC_WEIGHT_MEDIUM	},
31    {	"demibold", FC_WEIGHT_DEMIBOLD },
32    {	"bold",	    FC_WEIGHT_BOLD	},
33    {	"black",    FC_WEIGHT_BLACK	},
34};
35
36#define NUM_XLFD_WEIGHTS    (sizeof XftXlfdWeights/sizeof XftXlfdWeights[0])
37
38static XftSymbolic XftXlfdSlants[] = {
39    {	"r",	    FC_SLANT_ROMAN	},
40    {	"i",	    FC_SLANT_ITALIC	},
41    {	"o",	    FC_SLANT_OBLIQUE	},
42};
43
44#define NUM_XLFD_SLANTS    (sizeof XftXlfdSlants/sizeof XftXlfdSlants[0])
45
46/*
47 * Cut out one XLFD field, placing it in 'save' and return
48 * the start of 'save'
49 */
50static char *
51XftSplitStr (const char *field, char *save)
52{
53    char    *s = save;
54    char    c;
55
56    while (*field)
57    {
58	if (*field == '-')
59	    break;
60	c = *field++;
61	*save++ = c;
62    }
63    *save = 0;
64    return s;
65}
66
67/*
68 * convert one XLFD numeric field.  Return -1 if the field is '*'
69 */
70
71static const char *
72XftGetInt(const char *ptr, int *val)
73{
74    if (*ptr == '*') {
75	*val = -1;
76	ptr++;
77    } else
78	for (*val = 0; *ptr >= '0' && *ptr <= '9';)
79	    *val = *val * 10 + *ptr++ - '0';
80    if (*ptr == '-')
81	return ptr;
82    return (char *) 0;
83}
84
85_X_EXPORT FcPattern *
86XftXlfdParse (const char *xlfd_orig, FcBool ignore_scalable, FcBool complete)
87{
88    FcPattern	*pat;
89    const char	*xlfd = xlfd_orig;
90    const char	*foundry;
91    const char	*family;
92    const char	*weight_name;
93    const char	*slant;
94    const char	*registry;
95    const char	*encoding;
96    char	*save;
97    int		pixel;
98    int		point;
99    int		resx;
100    int		resy;
101    int		slant_value, weight_value;
102    double	dpixel;
103
104    if (*xlfd != '-')
105	return 0;
106    if (!(xlfd = strchr (foundry = ++xlfd, '-'))) return 0;
107    if (!(xlfd = strchr (family = ++xlfd, '-'))) return 0;
108    if (!(xlfd = strchr (weight_name = ++xlfd, '-'))) return 0;
109    if (!(xlfd = strchr (slant = ++xlfd, '-'))) return 0;
110    if (!(xlfd = strchr (/* setwidth_name = */ ++xlfd, '-'))) return 0;
111    if (!(xlfd = strchr (/* add_style_name = */ ++xlfd, '-'))) return 0;
112    if (!(xlfd = XftGetInt (++xlfd, &pixel))) return 0;
113    if (!(xlfd = XftGetInt (++xlfd, &point))) return 0;
114    if (!(xlfd = XftGetInt (++xlfd, &resx))) return 0;
115    if (!(xlfd = XftGetInt (++xlfd, &resy))) return 0;
116    if (!(xlfd = strchr (/* spacing = */ ++xlfd, '-'))) return 0;
117    if (!(xlfd = strchr (/* average_width = */ ++xlfd, '-'))) return 0;
118    if (!(xlfd = strchr (registry = ++xlfd, '-'))) return 0;
119    /* make sure no fields follow this one */
120    if ((xlfd = strchr (encoding = ++xlfd, '-'))) return 0;
121
122    if (!pixel)
123	return 0;
124
125    pat = FcPatternCreate ();
126    if (!pat)
127	return 0;
128
129    save = (char *) malloc (strlen (foundry) + 1);
130
131    if (!save) {
132	FcPatternDestroy (pat);
133	return 0;
134    }
135
136    if (!FcPatternAddString (pat, XFT_XLFD, (FcChar8 *) xlfd_orig)) goto bail;
137
138    XftSplitStr (foundry, save);
139    if (save[0] && strcmp (save, "*") != 0)
140	if (!FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) save)) goto bail;
141
142    XftSplitStr (family, save);
143    if (save[0] && strcmp (save, "*") != 0)
144	if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) save)) goto bail;
145
146    weight_value = _XftMatchSymbolic (XftXlfdWeights, NUM_XLFD_WEIGHTS,
147				      XftSplitStr (weight_name, save),
148				      FC_WEIGHT_MEDIUM);
149    if (!FcPatternAddInteger (pat, FC_WEIGHT, weight_value))
150	goto bail;
151
152    slant_value = _XftMatchSymbolic (XftXlfdSlants, NUM_XLFD_SLANTS,
153				     XftSplitStr (slant, save),
154				     FC_SLANT_ROMAN);
155    if (!FcPatternAddInteger (pat, FC_SLANT, slant_value))
156	goto bail;
157
158    dpixel = (double) pixel;
159
160    if (point > 0)
161    {
162	if (!FcPatternAddDouble (pat, FC_SIZE, ((double) point) / 10.0)) goto bail;
163	if (pixel <= 0 && resy > 0)
164	{
165	    dpixel = (double) point * (double) resy / 720.0;
166	}
167    }
168
169    if (dpixel > 0)
170	if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE, dpixel)) goto bail;
171
172    free (save);
173    return pat;
174
175bail:
176    free (save);
177    FcPatternDestroy (pat);
178    return 0;
179}
180