1 /* $XConsortium: fontxlfd.c /main/20 1996/09/28 16:49:26 rws $ */
2 /* $XFree86: xc/lib/font/util/fontxlfd.c,v 3.5 1996/12/23 06:02:34 dawes Exp $ */
6 Copyright (c) 1990 X Consortium
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
27 Except as contained in this notice, the name of the X Consortium shall
28 not be used in advertising or otherwise to promote the sale, use or
29 other dealings in this Software without prior written authorization
30 from the X Consortium.
35 * Author: Keith Packard, MIT X Consortium
39 #include "fontstruct.h"
43 #if !defined(X_NOT_STDC_ENV) || defined(SCO)
46 #if defined(X_NOT_STDC_ENV) || (defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV))
53 #include <stdio.h> /* for sprintf() */
64 for (*val = 0; *ptr >= '0' && *ptr <= '9';)
65 *val = *val * 10 + *ptr++ - '0';
71 #define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
72 #define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
76 static struct lconv *locale = 0;
78 static char *radix = ".", *plus = "+", *minus = "-";
85 char buffer[80], *p1, *p2;
89 /* Figure out what symbols apply in this locale */
93 locale = localeconv();
94 if (locale->decimal_point && *locale->decimal_point)
95 radix = locale->decimal_point;
96 if (locale->positive_sign && *locale->positive_sign)
97 plus = locale->positive_sign;
98 if (locale->negative_sign && *locale->negative_sign)
99 minus = locale->negative_sign;
102 /* Copy the first 80 chars of ptr into our local buffer, changing
103 symbols as needed. */
104 for (p1 = ptr, p2 = buffer;
105 *p1 && (p2 - buffer) < sizeof(buffer) - 1;
110 case '~': *p2 = *minus; break;
111 case '+': *p2 = *plus; break;
112 case '.': *p2 = *radix; break;
118 /* Now we have something that strtod() can interpret... do it. */
119 #ifndef X_NOT_STDC_ENV
120 *result = strtod(buffer, &p1);
121 /* Return NULL if failure, pointer past number if success */
122 return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer));
124 for (p1 = buffer; isspace(*p1); p1++)
126 if (sscanf(p1, "%lf", result) != 1)
128 while (!isspace(*p1))
130 return ptr + (p1 - buffer);
135 xlfd_double_to_text(value, buffer, space_required)
142 int ndigits, exponent;
147 locale = localeconv();
148 if (locale->decimal_point && *locale->decimal_point)
149 radix = locale->decimal_point;
150 if (locale->positive_sign && *locale->positive_sign)
151 plus = locale->positive_sign;
152 if (locale->negative_sign && *locale->negative_sign)
153 minus = locale->negative_sign;
156 /* Compute a format to use to render the number */
157 sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS);
162 /* Render the number using printf's idea of formatting */
163 sprintf(buffer, formatbuf, value);
165 /* Find and read the exponent value */
166 for (p1 = buffer + strlen(buffer);
167 *p1-- != 'e' && p1[1] != 'E';);
168 exponent = atoi(p1 + 2);
169 if (value == 0.0) exponent = 0;
171 /* Figure out how many digits are significant */
172 while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--;
174 while (p1 >= buffer) if (isdigit(*p1--)) ndigits++;
176 /* Figure out notation to use */
177 if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1)
180 sprintf(formatbuf, "%%.%dle", ndigits - 1);
181 sprintf(buffer, formatbuf, value);
186 ndigits -= exponent + 1;
187 if (ndigits < 0) ndigits = 0;
188 sprintf(formatbuf, "%%.%dlf", ndigits);
189 sprintf(buffer, formatbuf, value);
193 while (*p1 && *p1 != '0') p1++;
194 while (*p1++) p1[-1] = *p1;
198 /* Last step, convert the locale-specific sign and radix characters
200 for (p1 = buffer; *p1; p1++)
202 if (*p1 == *minus) *p1 = '~';
203 else if (*p1 == *plus) *p1 = '+';
204 else if (*p1 == *radix) *p1 = '.';
207 return buffer - space_required;
214 /* Utility for XLFD users to round numbers to XLFD_NDIGITS
215 significant digits. How do you round to n significant digits on
218 #if defined(i386) || defined(__i386__) || defined(__alpha__)
219 #if !defined(__EMX__)
222 /* if we have IEEE 754 fp, we can round to binary digits... */
224 #if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53)
227 #define M_LN2 0.69314718055994530942
230 #define M_LN10 2.30258509299404568402
233 /* convert # of decimal digits to # of binary digits */
234 #define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5))
245 /* do minor sanity check for IEEE 754 fp and correct byte order */
247 if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) {
250 * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits
254 d_exp = (d.b[7] << 4) | (d.b[6] >> 4);
256 i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
257 j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
261 if (k & 0x100) j = 1;
264 if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) {
265 /* mantissa overflow: increment exponent */
266 d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1);
268 d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4);
271 i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
272 j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
274 for (;--i>=0;) d.b[i] = 0;
280 #endif /* !__EMX__ */
281 #endif /* i386 || __i386__ */
284 * If not IEEE 754: Let printf() do it for you.
287 char formatbuf[40], buffer[40];
289 sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS);
290 sprintf(buffer, formatbuf, x);
296 GetMatrix(ptr, vals, which)
298 FontScalablePtr vals;
303 if (which == PIXELSIZE_MASK)
304 matrix = vals->pixel_matrix;
305 else if (which == POINTSIZE_MASK)
306 matrix = vals->point_matrix;
307 else return (char *)0;
309 while (isspace(*ptr)) ptr++;
312 /* This is a matrix containing real numbers. It would be nice
313 to use strtod() or sscanf() to read the numbers, but those
314 don't handle '~' for minus and we cannot force them to use a
315 "." for the radix. We'll have to do the hard work ourselves
318 if ((ptr = readreal(++ptr, matrix + 0)) &&
319 (ptr = readreal(ptr, matrix + 1)) &&
320 (ptr = readreal(ptr, matrix + 2)) &&
321 (ptr = readreal(ptr, matrix + 3)))
323 while (isspace(*ptr)) ptr++;
329 while (isspace(*ptr)) ptr++;
332 if (which == POINTSIZE_MASK)
333 vals->values_supplied |= POINTSIZE_ARRAY;
335 vals->values_supplied |= PIXELSIZE_ARRAY;
337 else ptr = (char *)0;
344 if (ptr = GetInt(ptr, &value))
346 vals->values_supplied &= ~which;
349 matrix[3] = (double)value;
350 if (which == POINTSIZE_MASK)
353 vals->values_supplied |= POINTSIZE_SCALAR;
356 vals->values_supplied |= PIXELSIZE_SCALAR;
357 /* If we're concocting the pixelsize array from a scalar,
358 we will need to normalize element 0 for the pixel shape.
359 This is done in FontFileCompleteXLFD(). */
360 matrix[0] = matrix[3];
361 matrix[1] = matrix[2] = 0.0;
365 if (which == POINTSIZE_MASK)
366 vals->values_supplied |= POINTSIZE_WILDCARD;
368 vals->values_supplied |= PIXELSIZE_WILDCARD;
376 static void append_ranges(fname, nranges, ranges)
386 for (i = 0; i < nranges && strlen(fname) < 1010; i++)
388 if (i) strcat(fname, " ");
389 sprintf(fname + strlen(fname), "%d",
391 if (ranges[i].min_char_low ==
392 ranges[i].max_char_low &&
393 ranges[i].min_char_high ==
394 ranges[i].max_char_high) continue;
395 sprintf(fname + strlen(fname), "_%d",
403 FontParseXLFDName(fname, vals, subst)
405 FontScalablePtr vals;
414 FontScalableRec tmpvals;
415 char replaceChar = '0';
421 bzero(&tmpvals, sizeof(tmpvals));
422 if (subst != FONT_XLFD_REPLACE_VALUE)
425 if (!(*(ptr = fname) == '-' || *ptr++ == '*' && *ptr == '-') || /* fndry */
426 !(ptr = strchr(ptr + 1, '-')) || /* family_name */
427 !(ptr1 = ptr = strchr(ptr + 1, '-')) || /* weight_name */
428 !(ptr = strchr(ptr + 1, '-')) || /* slant */
429 !(ptr = strchr(ptr + 1, '-')) || /* setwidth_name */
430 !(ptr = strchr(ptr + 1, '-')) || /* add_style_name */
431 !(ptr = strchr(ptr + 1, '-')) || /* pixel_size */
432 !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) ||
433 !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) ||
434 !(ptr = GetInt(ptr + 1, &tmpvals.x)) || /* resolution_x */
435 !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) || /* resolution_y */
436 !(ptr4 = ptr = strchr(ptr + 1, '-')) || /* spacing */
437 !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */
438 !(ptr = strchr(ptr + 1, '-')) || /* charset_registry */
439 strchr(ptr + 1, '-'))/* charset_encoding */
442 /* Lop off HP charset subsetting enhancement. Interpreting this
443 field requires allocating some space in which to return the
444 results. So, to prevent memory leaks, this procedure will simply
445 lop off and ignore charset subsetting, and initialize the
446 relevant vals fields to zero. It's up to the caller to make its
447 own call to FontParseRanges() if it's interested in the charset
450 if (subst != FONT_XLFD_REPLACE_NONE &&
451 (p = strchr(strrchr(fname, '-'), '[')))
453 tmpvals.values_supplied |= CHARSUBSET_SPECIFIED;
457 /* Fill in deprecated fields for the benefit of rasterizers that care
459 tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ?
460 (int)(tmpvals.pixel_matrix[3] + .5) :
461 (int)(tmpvals.pixel_matrix[3] - .5);
462 tmpvals.point = (tmpvals.point_matrix[3] >= 0) ?
463 (int)(tmpvals.point_matrix[3] * 10 + .5) :
464 (int)(tmpvals.point_matrix[3] * 10 - .5);
466 spacingLen = ptr4 - ptr3 + 1;
469 case FONT_XLFD_REPLACE_NONE:
472 case FONT_XLFD_REPLACE_STAR:
474 case FONT_XLFD_REPLACE_ZERO:
475 strcpy(tmpBuf, ptr2);
476 ptr5 = tmpBuf + (ptr5 - ptr2);
477 ptr3 = tmpBuf + (ptr3 - ptr2);
481 ptr = strchr(ptr, '-') + 1; /* skip weight */
482 ptr = strchr(ptr, '-') + 1; /* skip slant */
483 ptr = strchr(ptr, '-') + 1; /* skip setwidth_name */
484 ptr = strchr(ptr, '-') + 1; /* skip add_style_name */
486 if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024)
488 *ptr++ = replaceChar;
490 *ptr++ = replaceChar;
497 memmove(ptr, ptr3, spacingLen);
506 *ptr++ = replaceChar;
510 case FONT_XLFD_REPLACE_VALUE:
511 if (vals->values_supplied & PIXELSIZE_MASK)
513 tmpvals.values_supplied =
514 (tmpvals.values_supplied & ~PIXELSIZE_MASK) |
515 (vals->values_supplied & PIXELSIZE_MASK);
516 tmpvals.pixel_matrix[0] = vals->pixel_matrix[0];
517 tmpvals.pixel_matrix[1] = vals->pixel_matrix[1];
518 tmpvals.pixel_matrix[2] = vals->pixel_matrix[2];
519 tmpvals.pixel_matrix[3] = vals->pixel_matrix[3];
521 if (vals->values_supplied & POINTSIZE_MASK)
523 tmpvals.values_supplied =
524 (tmpvals.values_supplied & ~POINTSIZE_MASK) |
525 (vals->values_supplied & POINTSIZE_MASK);
526 tmpvals.point_matrix[0] = vals->point_matrix[0];
527 tmpvals.point_matrix[1] = vals->point_matrix[1];
528 tmpvals.point_matrix[2] = vals->point_matrix[2];
529 tmpvals.point_matrix[3] = vals->point_matrix[3];
535 if (vals->width >= 0)
536 tmpvals.width = vals->width;
537 else if (vals->width < -1) /* overload: -1 means wildcard */
538 tmpvals.width = -vals->width;
541 p = ptr1 + 1; /* weight field */
542 l = strchr(p, '-') - p;
543 sprintf(tmpBuf, "%*.*s", l, l, p);
545 p += l + 1; /* slant field */
546 l = strchr(p, '-') - p;
547 sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
549 p += l + 1; /* setwidth_name */
550 l = strchr(p, '-') - p;
551 sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
553 p += l + 1; /* add_style_name field */
554 l = strchr(p, '-') - p;
555 sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
558 if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY)
562 strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0],
564 strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1],
566 strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2],
568 strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3],
574 sprintf(tmpBuf + strlen(tmpBuf), "%d",
575 (int)(tmpvals.pixel_matrix[3] + .5));
578 if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
582 strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0],
584 strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1],
586 strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2],
588 strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3],
594 sprintf(tmpBuf + strlen(tmpBuf), "%d",
595 (int)(tmpvals.point_matrix[3] * 10.0 + .5));
597 sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s",
598 tmpvals.x, tmpvals.y,
599 spacingLen, spacingLen, ptr3, tmpvals.width, ptr5);
600 strcpy(ptr1 + 1, tmpBuf);
601 if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges)
604 append_ranges(fname, vals->nranges, vals->ranges);
610 fsRange *FontParseRanges(name, nranges)
617 fsRange *result = (fsRange *)0;
619 name = strchr(name, '-');
620 for (n = 1; name && n < 14; n++)
621 name = strchr(name + 1, '-');
624 if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0;
627 while (*p1 && *p1 != ']')
631 l = strtol(p1, &p2, 0);
632 if (p2 == p1 || l > 0xffff) break;
633 thisrange.max_char_low = thisrange.min_char_low = l & 0xff;
634 thisrange.max_char_high = thisrange.min_char_high = l >> 8;
637 if (*p1 == ']' || *p1 == ' ')
639 while (*p1 == ' ') p1++;
640 if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
645 l = strtol(++p1, &p2, 0);
646 if (p2 == p1 || l > 0xffff) break;
647 thisrange.max_char_low = l & 0xff;
648 thisrange.max_char_high = l >> 8;
650 if (*p1 == ']' || *p1 == ' ')
652 while (*p1 == ' ') p1++;
653 if (add_range(&thisrange, nranges, &result, TRUE) != Successful)