diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:29:02 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-25 19:29:02 +0000 |
commit | a46389d96c54351cd95614f1e5eae495f51957f0 (patch) | |
tree | 1354ccf9481f6196a5b128dd6da82401ccfd1364 /util.c |
Initial revision
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 409 |
1 files changed, 409 insertions, 0 deletions
@@ -0,0 +1,409 @@ +/* +Copyright (c) 2002-2003 by Juliusz Chroboczek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* $XFree86: xc/programs/fonttosfnt/util.c,v 1.8 2003/11/21 05:22:09 dawes Exp $ */ + +#include <time.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#ifndef __UNIXOS2__ +# include <math.h> +#else +# include <float.h> +#endif +#include <stdarg.h> + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_BDF_H +#include "fonttosfnt.h" + +#ifdef __GLIBC__ +#define HAVE_TIMEGM +#define HAVE_TM_GMTOFF +#endif + +#ifdef BSD +#define HAVE_TM_GMTOFF +#define GMTOFFMEMBER tm_gmtoff +#endif + +#ifdef SCO +#define HAVE_TM_GMTOFF +#define GMTOFFMEMBER tm_tzadj +#endif + +/* That's in POSIX */ +#define HAVE_TZSET + +#ifdef NEED_SETENV +extern int setenv(const char *name, const char *value, int overwrite); +extern void unsetenv(const char *name); +#endif + +char* +sprintf_reliable(char *f, ...) +{ + char *s; + va_list args; + va_start(args, f); + s = vsprintf_reliable(f, args); + va_end(args); + return s; +} + +char* +vsprintf_reliable(char *f, va_list args) +{ + int n, size = 12; + char *string; + while(1) { + if(size > 4096) + return NULL; + string = malloc(size); + if(!string) + return NULL; + n = vsnprintf(string, size, f, args); + if(n >= 0 && n < size) + return string; + else if(n >= size) + size = n + 1; + else + size = size * 3 / 2 + 1; + free(string); + } + /* NOTREACHED */ +} + +/* Build a UTF-16 string from a Latin-1 string. + Result is not NUL-terminated. */ +char * +makeUTF16(char *string) +{ + int i; + int n = strlen(string); + char *value = malloc(2 * n); + if(!value) + return NULL; + for(i = 0; i < n; i++) { + value[2 * i] = '\0'; + value[2 * i + 1] = string[i]; + } + return value; +} + +unsigned +makeName(char *s) +{ + return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; +} + +/* Like mktime(3), but UTC rather than local time */ +#if defined(HAVE_TIMEGM) +time_t +mktime_gmt(struct tm *tm) +{ + return timegm(tm); +} +#elif defined(HAVE_TM_GMTOFF) +time_t +mktime_gmt(struct tm *tm) +{ + time_t t; + struct tm *ltm; + + t = mktime(tm); + if(t < 0) + return -1; + ltm = localtime(&t); + if(ltm == NULL) + return -1; + return t + ltm->GMTOFFMEMBER; +} +#elif defined(HAVE_TZSET) +/* Taken from the Linux timegm(3) man page */ +time_t +mktime_gmt(struct tm *tm) +{ + time_t t; + char *tz; + + tz = getenv("TZ"); + setenv("TZ", "", 1); + tzset(); + t = mktime(tm); + if(tz) + setenv("TZ", tz, 1); + else + unsetenv("TZ"); + tzset(); + return t; +} +#else +#error no mktime_gmt implementation on this platform +#endif + +/* Return the current time as a signed 64-bit number of seconds since + midnight, 1 January 1904. This is apparently when the Macintosh + was designed. */ +int +macTime(int *hi, unsigned *lo) +{ + unsigned long diff; /* Not time_t */ + time_t macEpoch, current; + struct tm tm; + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + tm.tm_mday = 1; + tm.tm_mon = 1; + tm.tm_year = 4; + tm.tm_isdst = -1; + + macEpoch = mktime_gmt(&tm); + if(macEpoch < 0) return -1; + + current = time(NULL); + if(current < 0) + return -1; + + if(current < macEpoch) { + errno = EINVAL; + return -1; + } + + diff = current - macEpoch; +#if INT_MAX == LONG_MAX + *hi = 0; +#else + *hi = diff >> 32; +#endif + *lo = diff & 0xFFFFFFFF; + return 0; +} + +unsigned +faceFoundry(FT_Face face) +{ + int rc; + BDF_PropertyRec prop; + + rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + if(strcasecmp(prop.u.atom, "adobe") == 0) + return makeName("ADBE"); + else if(strcasecmp(prop.u.atom, "agfa") == 0) + return makeName("AGFA"); + else if(strcasecmp(prop.u.atom, "altsys") == 0) + return makeName("ALTS"); + else if(strcasecmp(prop.u.atom, "apple") == 0) + return makeName("APPL"); + else if(strcasecmp(prop.u.atom, "arphic") == 0) + return makeName("ARPH"); + else if(strcasecmp(prop.u.atom, "alltype") == 0) + return makeName("ATEC"); + else if(strcasecmp(prop.u.atom, "b&h") == 0) + return makeName("B&H "); + else if(strcasecmp(prop.u.atom, "bitstream") == 0) + return makeName("BITS"); + else if(strcasecmp(prop.u.atom, "dynalab") == 0) + return makeName("DYNA"); + else if(strcasecmp(prop.u.atom, "ibm") == 0) + return makeName("IBM "); + else if(strcasecmp(prop.u.atom, "itc") == 0) + return makeName("ITC "); + else if(strcasecmp(prop.u.atom, "interleaf") == 0) + return makeName("LEAF"); + else if(strcasecmp(prop.u.atom, "impress") == 0) + return makeName("IMPR"); + else if(strcasecmp(prop.u.atom, "larabiefonts") == 0) + return makeName("LARA"); + else if(strcasecmp(prop.u.atom, "linotype") == 0) + return makeName("LINO"); + else if(strcasecmp(prop.u.atom, "monotype") == 0) + return makeName("MT "); + else if(strcasecmp(prop.u.atom, "microsoft") == 0) + return makeName("MS "); + else if(strcasecmp(prop.u.atom, "urw") == 0) + return makeName("URW "); + else if(strcasecmp(prop.u.atom, "y&y") == 0) + return makeName("Y&Y "); + else + return makeName("UNKN"); + } + /* For now */ + return makeName("UNKN"); +} + + +int +faceWeight(FT_Face face) +{ + int rc; + BDF_PropertyRec prop; + rc = FT_Get_BDF_Property(face, "WEIGHT_NAME", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + if(strcasecmp(prop.u.atom, "thin") == 0) + return 100; + else if(strcasecmp(prop.u.atom, "extralight") == 0) + return 200; + else if(strcasecmp(prop.u.atom, "light") == 0) + return 300; + else if(strcasecmp(prop.u.atom, "medium") == 0) + return 500; + else if(strcasecmp(prop.u.atom, "semibold") == 0) + return 600; + else if(strcasecmp(prop.u.atom, "bold") == 0) + return 700; + else if(strcasecmp(prop.u.atom, "extrabold") == 0) + return 800; + else if(strcasecmp(prop.u.atom, "black") == 0) + return 900; + else + return 500; + } else + return 500; /* for now */ +} + +int +faceWidth(FT_Face face) +{ + int rc; + BDF_PropertyRec prop; + rc = FT_Get_BDF_Property(face, "SETWIDTH_NAME", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + if(strcasecmp(prop.u.atom, "ultracondensed") == 0) + return 1; + else if(strcasecmp(prop.u.atom, "extracondensed") == 0) + return 2; + else if(strcasecmp(prop.u.atom, "condensed") == 0) + return 3; + else if(strcasecmp(prop.u.atom, "semicondensed") == 0) + return 4; + else if(strcasecmp(prop.u.atom, "normal") == 0) + return 5; + else if(strcasecmp(prop.u.atom, "semiexpanded") == 0) + return 6; + else if(strcasecmp(prop.u.atom, "expanded") == 0) + return 7; + else if(strcasecmp(prop.u.atom, "extraexpanded") == 0) + return 8; + else if(strcasecmp(prop.u.atom, "ultraexpanded") == 0) + return 9; + else + return 5; + } else + return 5; /* for now */ +} + +int +faceItalicAngle(FT_Face face) +{ + int rc; + BDF_PropertyRec prop; + + rc = FT_Get_BDF_Property(face, "ITALIC_ANGLE", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER) { + return (prop.u.integer - 64 * 90) * (TWO_SIXTEENTH / 64); + } + + rc = FT_Get_BDF_Property(face, "SLANT", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + if(strcasecmp(prop.u.atom, "i") == 0 || + strcasecmp(prop.u.atom, "s") == 0) + return -30 * TWO_SIXTEENTH; + else + return 0; + } else + return 0; /* for now */ +} + +int +faceFlags(FT_Face face) +{ + int flags = 0; + BDF_PropertyRec prop; + int rc; + + if(faceWeight(face) >= 650) + flags |= FACE_BOLD; + rc = FT_Get_BDF_Property(face, "SLANT", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + if(strcasecmp(prop.u.atom, "i") == 0 || + strcasecmp(prop.u.atom, "s") == 0) + flags |= FACE_ITALIC; + } + return flags; +} + +char * +faceEncoding(FT_Face face) +{ + BDF_PropertyRec p1, p2; + int rc; + + rc = FT_Get_BDF_Property(face, "CHARSET_REGISTRY", &p1); + if(rc != 0 || p1.type != BDF_PROPERTY_TYPE_ATOM) + return NULL; + rc = FT_Get_BDF_Property(face, "CHARSET_ENCODING", &p2); + if(rc != 0 || p2.type != BDF_PROPERTY_TYPE_ATOM) + return NULL; + + return sprintf_reliable("%s-%s", p1.u.atom, p2.u.atom); +} + +int +degreesToFraction(int deg, int *num, int *den) +{ + double n, d; + double rad, val; + int i; + + if(deg <= -(60 * TWO_SIXTEENTH) || deg >= (60 * TWO_SIXTEENTH)) + goto fail; + + rad = (((double)deg) / TWO_SIXTEENTH) / 180.0 * M_PI; + + n = sin(-rad); + d = cos(rad); + + if(d < 0.001) + goto fail; + + val = atan2(n, d); + /* There must be a cleaner way */ + for(i = 1; i < 10000; i++) { + if((int)(d * i) != 0.0 && + fabs(atan2(ROUND(n * i), ROUND(d * i)) - val) < 0.05) { + *num = (int)ROUND(n * i); + *den = (int)ROUND(d * i); + return 0; + } + } + + fail: + *den = 1; + *num = 0; + return -1; +} + |