Imported Upstream version 2.13.0
[platform/upstream/fontconfig.git] / src / fcdefault.c
index 8ad1b1e..35973d7 100644 (file)
  */
 
 #include "fcint.h"
+#include <limits.h>
 #include <string.h>
 
+/* MT-safe */
+
 static const struct {
     FcObject   field;
     FcBool     value;
@@ -32,53 +35,204 @@ static const struct {
     { FC_HINTING_OBJECT,          FcTrue       },  /* !FT_LOAD_NO_HINTING */
     { FC_VERTICAL_LAYOUT_OBJECT,   FcFalse     },  /* FC_LOAD_VERTICAL_LAYOUT */
     { FC_AUTOHINT_OBJECT,         FcFalse      },  /* FC_LOAD_FORCE_AUTOHINT */
-    /* XXX: FC_GLOBAL_ADVANCE is deprecated */
     { FC_GLOBAL_ADVANCE_OBJECT,    FcTrue      },  /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
     { FC_EMBEDDED_BITMAP_OBJECT,   FcTrue      },  /* !FC_LOAD_NO_BITMAP */
     { FC_DECORATIVE_OBJECT,       FcFalse      },
+    { FC_SYMBOL_OBJECT,                   FcFalse      },
+    { FC_VARIABLE_OBJECT,         FcFalse      },
 };
 
 #define NUM_FC_BOOL_DEFAULTS   (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
 
+FcStrSet *default_langs;
+
 FcStrSet *
 FcGetDefaultLangs (void)
 {
-    FcStrSet *result = FcStrSetCreate ();
-    char *langs;
-
-    langs = getenv ("FC_LANG");
-    if (!langs || !langs[0])
-       langs = getenv ("LC_ALL");
-    if (!langs || !langs[0])
-       langs = getenv ("LC_CTYPE");
-    if (!langs || !langs[0])
-       langs = getenv ("LANG");
-    if (langs && langs[0])
+    FcStrSet *result;
+retry:
+    result = (FcStrSet *) fc_atomic_ptr_get (&default_langs);
+    if (!result)
     {
-       if (!FcStrSetAddLangs (result, langs))
+       char *langs;
+
+       result = FcStrSetCreate ();
+
+       langs = getenv ("FC_LANG");
+       if (!langs || !langs[0])
+           langs = getenv ("LC_ALL");
+       if (!langs || !langs[0])
+           langs = getenv ("LC_CTYPE");
+       if (!langs || !langs[0])
+           langs = getenv ("LANG");
+       if (langs && langs[0])
+       {
+           if (!FcStrSetAddLangs (result, langs))
+               FcStrSetAdd (result, (const FcChar8 *) "en");
+       }
+       else
            FcStrSetAdd (result, (const FcChar8 *) "en");
+
+       FcRefSetConst (&result->ref);
+       if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
+           FcRefInit (&result->ref, 1);
+           FcStrSetDestroy (result);
+           goto retry;
+       }
     }
-    else
-       FcStrSetAdd (result, (const FcChar8 *) "en");
 
     return result;
 }
 
+static FcChar8 *default_lang; /* MT-safe */
+
 FcChar8 *
 FcGetDefaultLang (void)
 {
-    static FcChar8 lang_local[128] = {0};
-    FcStrSet *langs;
+    FcChar8 *lang;
+retry:
+    lang = fc_atomic_ptr_get (&default_lang);
+    if (!lang)
+    {
+       FcStrSet *langs = FcGetDefaultLangs ();
+       lang = FcStrdup (langs->strs[0]);
+
+       if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
+           free (lang);
+           goto retry;
+       }
+    }
+
+    return lang;
+}
 
-    if (!lang_local[0])
+static FcChar8 *default_prgname;
+
+FcChar8 *
+FcGetPrgname (void)
+{
+    FcChar8 *prgname;
+retry:
+    prgname = fc_atomic_ptr_get (&default_prgname);
+    if (!prgname)
     {
-       langs = FcGetDefaultLangs ();
-       strncpy ((char *)lang_local, (const char *)langs->strs[0], 127);
-       lang_local[127] = 0;
+#ifdef _WIN32
+       char buf[MAX_PATH+1];
+
+       /* TODO This is ASCII-only; fix it. */
+       if (GetModuleFileNameA (GetModuleHandle (NULL), buf, sizeof (buf) / sizeof (buf[0])) > 0)
+       {
+           char *p;
+           unsigned int len;
+
+           p = strrchr (buf, '\\');
+           if (p)
+               p++;
+           else
+               p = buf;
+
+           len = strlen (p);
+
+           if (len > 4 && 0 == strcmp (p + len - 4, ".exe"))
+           {
+               len -= 4;
+               buf[len] = '\0';
+           }
+
+           prgname = FcStrdup (p);
+       }
+#elif defined (HAVE_GETPROGNAME)
+       const char *q = getprogname ();
+       if (q)
+           prgname = FcStrdup (q);
+       else
+           prgname = FcStrdup ("");
+#else
+# if defined (HAVE_GETEXECNAME)
+       char *p = FcStrdup(getexecname ());
+# elif defined (HAVE_READLINK)
+       size_t size = FC_PATH_MAX;
+       char *p = NULL;
+
+       while (1)
+       {
+           char *buf = malloc (size);
+           ssize_t len;
+
+           if (!buf)
+               break;
+
+           len = readlink ("/proc/self/exe", buf, size - 1);
+           if (len < 0)
+           {
+               free (buf);
+               break;
+           }
+           if (len < size - 1)
+           {
+               buf[len] = 0;
+               p = buf;
+               break;
+           }
+
+           free (buf);
+           size *= 2;
+       }
+# else
+       char *p = NULL;
+# endif
+       if (p)
+       {
+           char *r = strrchr (p, '/');
+           if (r)
+               r++;
+           else
+               r = p;
+
+           prgname = FcStrdup (r);
+       }
+
+       if (!prgname)
+           prgname = FcStrdup ("");
+
+       if (p)
+           free (p);
+#endif
+
+       if (!fc_atomic_ptr_cmpexch (&default_prgname, NULL, prgname)) {
+           free (prgname);
+           goto retry;
+       }
+    }
+
+    if (prgname && !prgname[0])
+       return NULL;
+
+    return prgname;
+}
+
+void
+FcDefaultFini (void)
+{
+    FcChar8  *lang;
+    FcStrSet *langs;
+    FcChar8  *prgname;
+
+    lang = fc_atomic_ptr_get (&default_lang);
+    if (lang && fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
+       free (lang);
+    }
+
+    langs = fc_atomic_ptr_get (&default_langs);
+    if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
+       FcRefInit (&langs->ref, 1);
        FcStrSetDestroy (langs);
     }
 
-    return lang_local;
+    prgname = fc_atomic_ptr_get (&default_prgname);
+    if (prgname && fc_atomic_ptr_cmpexch (&default_prgname, prgname, NULL)) {
+       free (prgname);
+    }
 }
 
 void
@@ -86,9 +240,10 @@ FcDefaultSubstitute (FcPattern *pattern)
 {
     FcValue v, namelang, v2;
     int            i;
+    double     dpi, size, scale, pixelsize;
 
     if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch )
-       FcPatternObjectAddInteger (pattern, FC_WEIGHT_OBJECT, FC_WEIGHT_MEDIUM);
+       FcPatternObjectAddInteger (pattern, FC_WEIGHT_OBJECT, FC_WEIGHT_NORMAL);
 
     if (FcPatternObjectGet (pattern, FC_SLANT_OBJECT, 0, &v) == FcResultNoMatch)
        FcPatternObjectAddInteger (pattern, FC_SLANT_OBJECT, FC_SLANT_ROMAN);
@@ -100,32 +255,37 @@ FcDefaultSubstitute (FcPattern *pattern)
        if (FcPatternObjectGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch)
            FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value);
 
-    if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) == FcResultNoMatch)
+    if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch)
     {
-       double  dpi, size, scale;
+       FcRange *r;
+       double b, e;
+       if (FcPatternObjectGetRange (pattern, FC_SIZE_OBJECT, 0, &r) == FcResultMatch && FcRangeGetDouble (r, &b, &e))
+           size = (b + e) * .5;
+       else
+           size = 12.0L;
+    }
+    if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch)
+       scale = 1.0;
+    if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch)
+       dpi = 75.0;
 
-       if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch)
-       {
-           size = 12.0;
-           (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT);
-           FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size);
-       }
-       if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch)
-       {
-           scale = 1.0;
-           (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT);
-           FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale);
-       }
-       size *= scale;
-       if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch)
-       {
-           dpi = 75.0;
-           (void) FcPatternObjectDel (pattern, FC_DPI_OBJECT);
-           FcPatternObjectAddDouble (pattern, FC_DPI_OBJECT, dpi);
-       }
-       size *= dpi / 72.0;
-       FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, size);
+    if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) != FcResultMatch)
+    {
+       (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT);
+       FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale);
+       pixelsize = size * scale;
+       (void) FcPatternObjectDel (pattern, FC_DPI_OBJECT);
+       FcPatternObjectAddDouble (pattern, FC_DPI_OBJECT, dpi);
+       pixelsize *= dpi / 72.0;
+       FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, pixelsize);
+    }
+    else
+    {
+       size = v.u.d;
+       size = size / dpi * 72.0 / scale;
     }
+    (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT);
+    FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size);
 
     if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch)
     {
@@ -154,7 +314,7 @@ FcDefaultSubstitute (FcPattern *pattern)
      * exact matched "en" has higher score than ll-cc.
      */
     v2.type = FcTypeString;
-    v2.u.s = FcSharedStr ((FcChar8 *)"en-us");
+    v2.u.s = (FcChar8 *) "en-us";
     if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch)
     {
        FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue);
@@ -170,7 +330,13 @@ FcDefaultSubstitute (FcPattern *pattern)
        FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
        FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
     }
-    FcSharedStrFree (v2.u.s);
+
+    if (FcPatternObjectGet (pattern, FC_PRGNAME_OBJECT, 0, &v) == FcResultNoMatch)
+    {
+       FcChar8 *prgname = FcGetPrgname ();
+       if (prgname)
+           FcPatternObjectAddString (pattern, FC_PRGNAME_OBJECT, prgname);
+    }
 }
 #define __fcdefault__
 #include "fcaliastail.h"