Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright  2000 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #include "xftint.h"
     24 
     25 static XftSymbolic XftXlfdWeights[] = {
     26     {	"light",    FC_WEIGHT_LIGHT	},
     27     {	"medium",   FC_WEIGHT_MEDIUM	},
     28     {	"regular",  FC_WEIGHT_MEDIUM	},
     29     {	"demibold", FC_WEIGHT_DEMIBOLD },
     30     {	"bold",	    FC_WEIGHT_BOLD	},
     31     {	"black",    FC_WEIGHT_BLACK	},
     32 };
     33 
     34 #define NUM_XLFD_WEIGHTS    (sizeof XftXlfdWeights/sizeof XftXlfdWeights[0])
     35 
     36 static XftSymbolic XftXlfdSlants[] = {
     37     {	"r",	    FC_SLANT_ROMAN	},
     38     {	"i",	    FC_SLANT_ITALIC	},
     39     {	"o",	    FC_SLANT_OBLIQUE	},
     40 };
     41 
     42 #define NUM_XLFD_SLANTS    (sizeof XftXlfdSlants/sizeof XftXlfdSlants[0])
     43 
     44 /*
     45  * Cut out one XLFD field, placing it in 'save' and return
     46  * the start of 'save'
     47  */
     48 static char *
     49 XftSplitStr (const char *field, char *save)
     50 {
     51     char    *s = save;
     52     char    c;
     53 
     54     while (*field)
     55     {
     56 	if (*field == '-')
     57 	    break;
     58 	c = *field++;
     59 	*save++ = c;
     60     }
     61     *save = 0;
     62     return s;
     63 }
     64 
     65 /*
     66  * convert one XLFD numeric field.  Return -1 if the field is '*'
     67  */
     68 
     69 static const char *
     70 XftGetInt(const char *ptr, int *val)
     71 {
     72     if (*ptr == '*') {
     73 	*val = -1;
     74 	ptr++;
     75     } else
     76 	for (*val = 0; *ptr >= '0' && *ptr <= '9';)
     77 	    *val = *val * 10 + *ptr++ - '0';
     78     if (*ptr == '-')
     79 	return ptr;
     80     return (char *) 0;
     81 }
     82 
     83 _X_EXPORT FcPattern *
     84 XftXlfdParse (const char *xlfd_orig, FcBool ignore_scalable _X_UNUSED, FcBool complete _X_UNUSED)
     85 {
     86     FcPattern	*pat;
     87     const char	*xlfd = xlfd_orig;
     88     const char	*foundry;
     89     const char	*family;
     90     const char	*weight_name;
     91     const char	*slant;
     92     char	*save;
     93     int		pixel;
     94     int		point;
     95     int		resx;
     96     int		resy;
     97     int		slant_value, weight_value;
     98     double	dpixel;
     99 
    100     if (*xlfd != '-')
    101 	return NULL;
    102     if (!(xlfd = strchr (foundry = ++xlfd, '-'))) return NULL;
    103     if (!(xlfd = strchr (family = ++xlfd, '-'))) return NULL;
    104     if (!(xlfd = strchr (weight_name = ++xlfd, '-'))) return NULL;
    105     if (!(xlfd = strchr (slant = ++xlfd, '-'))) return NULL;
    106     if (!(xlfd = strchr (/* setwidth_name = */ ++xlfd, '-'))) return NULL;
    107     if (!(xlfd = strchr (/* add_style_name = */ ++xlfd, '-'))) return NULL;
    108     if (!(xlfd = XftGetInt (++xlfd, &pixel))) return NULL;
    109     if (!(xlfd = XftGetInt (++xlfd, &point))) return NULL;
    110     if (!(xlfd = XftGetInt (++xlfd, &resx))) return NULL;
    111     if (!(xlfd = XftGetInt (++xlfd, &resy))) return NULL;
    112     if (!(xlfd = strchr (/* spacing = */ ++xlfd, '-'))) return NULL;
    113     if (!(xlfd = strchr (/* average_width = */ ++xlfd, '-'))) return NULL;
    114     if (!(xlfd = strchr (/* registry = */ ++xlfd, '-'))) return NULL;
    115     /* make sure no fields follow this one */
    116     if ((/* xlfd = */ strchr (/* encoding = */ ++xlfd, '-'))) return NULL;
    117 
    118     if (!pixel)
    119 	return NULL;
    120 
    121     pat = FcPatternCreate ();
    122     if (!pat)
    123 	return NULL;
    124 
    125     save = (char *) malloc (strlen (foundry) + 1);
    126 
    127     if (!save) {
    128 	FcPatternDestroy (pat);
    129 	return NULL;
    130     }
    131 
    132     if (!FcPatternAddString (pat, XFT_XLFD, (const FcChar8 *) xlfd_orig)) goto bail;
    133 
    134     XftSplitStr (foundry, save);
    135     if (save[0] && strcmp (save, "*") != 0)
    136 	if (!FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) save)) goto bail;
    137 
    138     XftSplitStr (family, save);
    139     if (save[0] && strcmp (save, "*") != 0)
    140 	if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) save)) goto bail;
    141 
    142     weight_value = _XftMatchSymbolic (XftXlfdWeights, NUM_XLFD_WEIGHTS,
    143 				      XftSplitStr (weight_name, save),
    144 				      FC_WEIGHT_MEDIUM);
    145     if (!FcPatternAddInteger (pat, FC_WEIGHT, weight_value))
    146 	goto bail;
    147 
    148     slant_value = _XftMatchSymbolic (XftXlfdSlants, NUM_XLFD_SLANTS,
    149 				     XftSplitStr (slant, save),
    150 				     FC_SLANT_ROMAN);
    151     if (!FcPatternAddInteger (pat, FC_SLANT, slant_value))
    152 	goto bail;
    153 
    154     dpixel = (double) pixel;
    155 
    156     if (point > 0)
    157     {
    158 	if (!FcPatternAddDouble (pat, FC_SIZE, ((double) point) / 10.0)) goto bail;
    159 	if (pixel <= 0 && resy > 0)
    160 	{
    161 	    dpixel = (double) point * (double) resy / 720.0;
    162 	}
    163     }
    164 
    165     if (dpixel > 0)
    166 	if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE, dpixel)) goto bail;
    167 
    168     free (save);
    169     return pat;
    170 
    171 bail:
    172     free (save);
    173     FcPatternDestroy (pat);
    174     return NULL;
    175 }
    176