Exemplo n.º 1
0
FcFontSet * fcinfo_match(FcFontSet *fontset, const FcPattern *filter)
{
  int f;

  FcFontSet *result;

  FcChar8 *family, *style, *file;
  FcChar8 *next_family, *next_style;

  double size;

  FcBool scalable;
  FcPattern *pat, *match = NULL;
  FcResult r;

  FcInit();

  if (fontset->nfont == 0)
  {
    result = FcFontSetCreate();
    return result;
  }

  /* fc-match "Misc Fixed:style=Bold" gives many files with 
     various pixelsizes plus two "encodings" ('general' and 
     'ISO8859-1', ISO8859-1 is subset of general) 

     we want only one card for family,style pair

     for MiscFixedBold.html we will take informations from
     file 9x18B.pcf.gz (biggest size and general encoding)

     from fcinfo(), fontset is sorted a way that pattern
     created from 9x18B.pcf.gz comes first in 
     "Misc Fixed:style=Bold" interval (the biggest pixel size
     and subset of supported languages, see pattern_compare()). */

  result = FcFontSetCreate();
  for (f = 0; f < fontset->nfont; )
  {
    /* bitmap fonts: */
    /* we are here always on the best file in FC_LANG terms */
    /* we need it for displaying the widest range of supported languages */
    /* identify it by FC_FILE for FcFontMatch() */
    if (filter)
      pat = FcPatternDuplicate(filter);
    else
      pat = FcPatternCreate();
    assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                        LANG_EN, &family) == FcResultMatch);
    FcPatternAddString(pat, FC_FAMILY, family);
    if (fcinfo_get_translated_string(fontset->fonts[f], FC_STYLE, 
                                     LANG_EN, &style) == FcResultMatch)
      FcPatternAddString(pat, FC_STYLE, style);
    if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
        == FcResultMatch)
      FcPatternAddString(pat, FC_FILE, file);

    FcConfigSubstitute(NULL, pat, FcMatchPattern);
    FcDefaultSubstitute(pat);
    match = FcFontMatch(NULL, pat, &r);
    assert(r == FcResultMatch);
    /* should not be needed: FcConfigSubstitute(NULL, match, FcMatchFont); */
    FcPatternDestroy(pat);

    assert(FcPatternGetBool(match, FC_SCALABLE, 0, &scalable)  
           == FcResultMatch);

/*    fprintf(stdout, "Family: %s Style: %s\n", next_family, next_style);
    fprintf(stdout, "        %s\n", file);*/

    /* figure out sizes font provide (needed for specimen) and skip same */
    /* family,style pairs (see e. g. Misc Fixed) */
    if (! scalable)
    {
      next_family = family;
      next_style  = style;
      /* unfortunately e. g. 'ETL Fixed' and 'ETL fixed' 
         are present on my system */

      while (FcStrCmpIgnoreCase(next_family, family) == 0 &&
             FcStrCmpIgnoreCase(next_style, style) == 0)
      {
        if (FcPatternGetDouble(fontset->fonts[f], FC_PIXEL_SIZE, 0, &size)
                 == FcResultMatch)
        {
          if (! pattern_contains_size(match, size))
          {
            FcPatternAddDouble(match, FC_PIXEL_SIZE, size);
            if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
                     == FcResultMatch)
              FcPatternAddString(match, FC_FILE, file);
            /*fprintf(stdout, "       %s\n", file);*/
          }
        }

        if (f + 1 == fontset->nfont)  /* last family,style pair at all */
        {
          f++;
          break;
        }

        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_FAMILY, 
                                            LANG_EN, &next_family)
               == FcResultMatch);
        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_STYLE,
                                            LANG_EN, &next_style)
               == FcResultMatch);
        f++;
      }
    }
    else /* family Efont Serif Regular is spread (unintentionally) over */
    {    /* 5 files (Efont Serif <X> should be spread over 2 files,  */
         /* normal and 'Alternate'), so this is needed anyway: */
      FcPatternDel(match, FC_FILE);
      next_family = family;
      next_style  = style;

      while (FcStrCmpIgnoreCase(next_family, family) == 0 &&
             FcStrCmpIgnoreCase(next_style, style) == 0)
      {
        if (FcPatternGetString(fontset->fonts[f], FC_FILE, 0, &file)
                == FcResultMatch)
          FcPatternAddString(match, FC_FILE, file);

        if (f + 1 == fontset->nfont)  /* last family,style pair at all */
        {
          f++;
          break;
        }

        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_FAMILY, 
                                            LANG_EN, &next_family)
               == FcResultMatch);
        assert(fcinfo_get_translated_string(fontset->fonts[f + 1], FC_STYLE,
                                            LANG_EN, &next_style)
               == FcResultMatch);

        f++;
      }
    }

    /* don't add ethio16f-uni.pcf, johabg16.pcf and similar with reported 
       empty charset */
    if (! empty_charset(match))
      FcFontSetAdd(result, FcPatternDuplicate(match));
  }

  if (match)
    FcPatternDestroy(match);
  return result;
}
Exemplo n.º 2
0
void QFontconfigDatabase::populateFontDatabase()
{
    FcInitReinitialize();
    FcFontSet  *fonts;

    {
        FcObjectSet *os = FcObjectSetCreate();
        FcPattern *pattern = FcPatternCreate();
        const char *properties [] = {
            FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
            FC_SPACING, FC_FILE, FC_INDEX,
            FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
            FC_WIDTH,
#if FC_VERSION >= 20297
            FC_CAPABILITY,
#endif
            (const char *)0
        };
        const char **p = properties;
        while (*p) {
            FcObjectSetAdd(os, *p);
            ++p;
        }
        fonts = FcFontList(0, pattern, os);
        FcObjectSetDestroy(os);
        FcPatternDestroy(pattern);
    }

    for (int i = 0; i < fonts->nfont; i++)
        populateFromPattern(fonts->fonts[i]);

    FcFontSetDestroy (fonts);

    struct FcDefaultFont {
        const char *qtname;
        const char *rawname;
        bool fixed;
    };
    const FcDefaultFont defaults[] = {
        { "Serif", "serif", false },
        { "Sans Serif", "sans-serif", false },
        { "Monospace", "monospace", true },
        { 0, 0, false }
    };
    const FcDefaultFont *f = defaults;
    // aliases only make sense for 'common', not for any of the specials
    QSupportedWritingSystems ws;
    ws.setSupported(QFontDatabase::Latin);

    while (f->qtname) {
        QString familyQtName = QString::fromLatin1(f->qtname);
        registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,0);
        registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,0);
        registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,0);
        ++f;
    }

    //Lighthouse has very lazy population of the font db. We want it to be initialized when
    //QApplication is constructed, so that the population procedure can do something like this to
    //set the default font
//    const FcDefaultFont *s = defaults;
//    QFont font("Sans Serif");
//    font.setPointSize(9);
//    QApplication::setFont(font);
}
Exemplo n.º 3
0
FcPattern *
FcNameParse (const FcChar8 *name)
{
    FcChar8		*save;
    FcPattern		*pat;
    double		d;
    FcChar8		*e;
    FcChar8		delim;
    FcValue		v;
    const FcObjectType	*t;
    const FcConstant	*c;

    /* freed below */
    save = malloc (strlen ((char *) name) + 1);
    if (!save)
	goto bail0;
    pat = FcPatternCreate ();
    if (!pat)
	goto bail1;

    for (;;)
    {
	name = FcNameFindNext (name, "-,:", save, &delim);
	if (save[0])
	{
	    if (!FcPatternAddString (pat, FC_FAMILY, save))
		goto bail2;
	}
	if (delim != ',')
	    break;
    }
    if (delim == '-')
    {
	for (;;)
	{
	    name = FcNameFindNext (name, "-,:", save, &delim);
	    d = strtod ((char *) save, (char **) &e);
	    if (e != save)
	    {
		if (!FcPatternAddDouble (pat, FC_SIZE, d))
		    goto bail2;
	    }
	    if (delim != ',')
		break;
	}
    }
    while (delim == ':')
    {
	name = FcNameFindNext (name, "=_:", save, &delim);
	if (save[0])
	{
	    if (delim == '=' || delim == '_')
	    {
		t = FcNameGetObjectType ((char *) save);
		for (;;)
		{
		    name = FcNameFindNext (name, ":,", save, &delim);
		    if (t)
		    {
			v = FcNameConvert (t->type, save);
			if (!FcPatternAdd (pat, t->object, v, FcTrue))
			{
			    FcValueDestroy (v);
			    goto bail2;
			}
			FcValueDestroy (v);
		    }
		    if (delim != ',')
			break;
		}
	    }
	    else
	    {
		if ((c = FcNameGetConstant (save)))
		{
		    t = FcNameGetObjectType ((char *) c->object);
		    if (t == NULL)
			goto bail2;
		    switch ((int) t->type) {
		    case FcTypeInteger:
		    case FcTypeDouble:
			if (!FcPatternAddInteger (pat, c->object, c->value))
			    goto bail2;
			break;
		    case FcTypeBool:
			if (!FcPatternAddBool (pat, c->object, c->value))
			    goto bail2;
			break;
		    default:
			break;
		    }
		}
	    }
	}
    }

    free (save);
    return pat;

bail2:
    FcPatternDestroy (pat);
bail1:
    free (save);
bail0:
    return 0;
}
Exemplo n.º 4
0
/**
 * \brief Low-level font selection.
 * \param priv private data
 * \param family font family
 * \param treat_family_as_pattern treat family as fontconfig pattern
 * \param bold font weight value
 * \param italic font slant value
 * \param index out: font index inside a file
 * \param code: the character that should be present in the font, can be 0
 * \return font file path
*/
static char *select_font(ASS_Library *library, FCInstance *priv,
                          const char *family, int treat_family_as_pattern,
                          unsigned bold, unsigned italic, int *index,
                          uint32_t code)
{
    FcBool rc;
    FcResult result;
    FcPattern *pat = NULL, *rpat = NULL;
    int r_index, r_slant, r_weight;
    FcChar8 *r_family, *r_style, *r_file, *r_fullname;
    FcBool r_outline, r_embolden;
    FcCharSet *r_charset;
    FcFontSet *ffullname = NULL, *fsorted = NULL, *fset = NULL;
    int curf;
    char *retval = NULL;
    int family_cnt = 0;

    *index = 0;

    if (treat_family_as_pattern)
        pat = FcNameParse((const FcChar8 *) family);
    else
        pat = FcPatternCreate();

    if (!pat)
        goto error;

    if (!treat_family_as_pattern) {
        FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family);

        // In SSA/ASS fonts are sometimes referenced by their "full name",
        // which is usually a concatenation of family name and font
        // style (ex. Ottawa Bold). Full name is available from
        // FontConfig pattern element FC_FULLNAME, but it is never
        // used for font matching.
        // Therefore, I'm removing words from the end of the name one
        // by one, and adding shortened names to the pattern. It seems
        // that the first value (full name in this case) has
        // precedence in matching.
        // An alternative approach could be to reimplement FcFontSort
        // using FC_FULLNAME instead of FC_FAMILY.
        family_cnt = 1;
        {
            char *s = strdup(family);
            if (!s)
                goto error;
            char *p = s + strlen(s);
            while (--p > s)
                if (*p == ' ' || *p == '-') {
                    *p = '\0';
                    FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) s);
                    ++family_cnt;
                }
            free(s);
        }
    }
    FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
    FcPatternAddInteger(pat, FC_SLANT, italic);
    FcPatternAddInteger(pat, FC_WEIGHT, bold);

    FcDefaultSubstitute(pat);

    rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern);
    if (!rc)
        goto error;
    /* Fontconfig defaults include a language setting, which it sets based on
     * some environment variables or defaults to "en". Unset this as we don't
     * know the real language, and because some some attached fonts lack
     * non-ascii characters included in fontconfig's list of characters
     * required for English support and therefore don't match the lang=en
     * criterion.
     */
    FcPatternDel(pat, "lang");

    fsorted = FcFontSort(priv->config, pat, FcFalse, NULL, &result);
    ffullname = match_fullname(library, priv, family, bold, italic);
    if (!fsorted || !ffullname)
        goto error;

    fset = FcFontSetCreate();
    for (curf = 0; curf < ffullname->nfont; ++curf) {
        FcPattern *curp = ffullname->fonts[curf];
        FcPatternReference(curp);
        FcFontSetAdd(fset, curp);
    }
    for (curf = 0; curf < fsorted->nfont; ++curf) {
        FcPattern *curp = fsorted->fonts[curf];
        FcPatternReference(curp);
        FcFontSetAdd(fset, curp);
    }

    for (curf = 0; curf < fset->nfont; ++curf) {
        FcPattern *curp = fset->fonts[curf];

        result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline);
        if (result != FcResultMatch)
            continue;
        if (r_outline != FcTrue)
            continue;
        if (!code)
            break;
        result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset);
        if (result != FcResultMatch)
            continue;
        if (FcCharSetHasChar(r_charset, code))
            break;
    }

    if (curf >= fset->nfont)
        goto error;

    if (!treat_family_as_pattern) {
        // Remove all extra family names from original pattern.
        // After this, FcFontRenderPrepare will select the most relevant family
        // name in case there are more than one of them.
        for (; family_cnt > 1; --family_cnt)
            FcPatternRemove(pat, FC_FAMILY, family_cnt - 1);
    }

    rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]);
    if (!rpat)
        goto error;

    result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index);
    if (result != FcResultMatch)
        goto error;
    *index = r_index;

    result = FcPatternGetString(rpat, FC_FILE, 0, &r_file);
    if (result != FcResultMatch)
        goto error;
    retval = strdup((const char *) r_file);
    if (!retval)
        goto error;

    result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family);
    if (result != FcResultMatch)
        r_family = NULL;

    result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname);
    if (result != FcResultMatch)
        r_fullname = NULL;

    if (!treat_family_as_pattern &&
        !(r_family && strcasecmp((const char *) r_family, family) == 0) &&
        !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0)) {
        char *fallback = (char *) (r_fullname ? r_fullname : r_family);
        if (code) {
            ass_msg(library, MSGL_WARN,
                    "fontconfig: cannot find glyph U+%04X in font '%s', falling back to '%s'",
                    (unsigned int)code, family, fallback);
        } else {
            ass_msg(library, MSGL_WARN,
                    "fontconfig: cannot find font '%s', falling back to '%s'",
                    family, fallback);
        }
    }

    result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style);
    if (result != FcResultMatch)
        r_style = NULL;

    result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant);
    if (result != FcResultMatch)
        r_slant = 0;

    result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight);
    if (result != FcResultMatch)
        r_weight = 0;

    result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden);
    if (result != FcResultMatch)
        r_embolden = 0;

    ass_msg(library, MSGL_V,
           "Font info: family '%s', style '%s', fullname '%s',"
           " slant %d, weight %d%s", (const char *) r_family,
           (const char *) r_style, (const char *) r_fullname, r_slant,
           r_weight, r_embolden ? ", embolden" : "");

  error:
    if (pat)
        FcPatternDestroy(pat);
    if (rpat)
        FcPatternDestroy(rpat);
    if (fsorted)
        FcFontSetDestroy(fsorted);
    if (ffullname)
        FcFontSetDestroy(ffullname);
    if (fset)
        FcFontSetDestroy(fset);
    return retval;
}
Exemplo n.º 5
0
/* Constructor of the object : it allocates memory and initializes the member
 * of the new object.
 * The user must give the FcPattern of the font or the master (which may be NULL
 * in which case the character map will be empty).
 */
__GLCcharMap* __glcCharMapCreate(const __GLCmaster* inMaster,
				 const __GLCcontext* inContext)
{
  __GLCcharMap* This = NULL;

  assert(inContext);

  This = (__GLCcharMap*)__glcMalloc(sizeof(__GLCcharMap));
  if (!This) {
    __glcRaiseError(GLC_RESOURCE_ERROR);
    return NULL;
  }
  memset(This, 0, sizeof(__GLCcharMap));

  This->charSet = FcCharSetCreate();
  if (!This->charSet) {
    __glcRaiseError(GLC_RESOURCE_ERROR);
    __glcFree(This);
    return NULL;
  }

  if (inMaster) {
    FcCharSet* charSet = NULL;
    FcFontSet* fontSet = NULL;
    int i = 0;
    FcObjectSet* objectSet = NULL;
    FcPattern* pattern = FcPatternCreate();

    if (!pattern) {
      __glcRaiseError(GLC_RESOURCE_ERROR);
      FcCharSetDestroy(This->charSet);
      __glcFree(This);
      return NULL;
    }

    objectSet = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, FC_SPACING, FC_OUTLINE,
				 FC_CHARSET, NULL);
    if (!objectSet) {
      __glcRaiseError(GLC_RESOURCE_ERROR);
      FcPatternDestroy(pattern);
      FcCharSetDestroy(This->charSet);
      __glcFree(This);
      return NULL;
    }

    fontSet = FcFontList(inContext->config, pattern, objectSet);
    FcObjectSetDestroy(objectSet);
    FcPatternDestroy(pattern);
    if (!fontSet) {
      __glcRaiseError(GLC_RESOURCE_ERROR);
      FcCharSetDestroy(This->charSet);
      __glcFree(This);
      return NULL;
    }

    for (i = 0; i < fontSet->nfont; i++) {
      FcChar8* family = NULL;
      int fixed = 0;
      FcChar8* foundry = NULL;
      FcBool outline = FcFalse;
      FcBool equal = FcFalse;
#ifdef DEBUGMODE
      FcResult result = FcResultMatch;

      result = FcPatternGetBool(fontSet->fonts[i], FC_OUTLINE, 0, &outline);
      assert(result != FcResultTypeMismatch);
#else
      FcPatternGetBool(fontSet->fonts[i], FC_OUTLINE, 0, &outline);
#endif

      /* Check whether the glyphs are outlines */
      if (!outline)
	continue;

#ifdef DEBUGMODE
      result = FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &family);
      assert(result != FcResultTypeMismatch);
      result = FcPatternGetString(fontSet->fonts[i], FC_FOUNDRY, 0, &foundry);
      assert(result != FcResultTypeMismatch);
      result = FcPatternGetInteger(fontSet->fonts[i], FC_SPACING, 0, &fixed);
      assert(result != FcResultTypeMismatch);
#else
      FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &family);
      FcPatternGetString(fontSet->fonts[i], FC_FOUNDRY, 0, &foundry);
      FcPatternGetInteger(fontSet->fonts[i], FC_SPACING, 0, &fixed);
#endif

      if (foundry)
	pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family,
				 FC_FOUNDRY, FcTypeString, foundry, FC_SPACING,
				 FcTypeInteger, fixed, NULL);
      else
	pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family,
				 FC_SPACING, FcTypeInteger, fixed, NULL);

      if (!pattern) {
	__glcRaiseError(GLC_RESOURCE_ERROR);
	FcCharSetDestroy(This->charSet);
	FcFontSetDestroy(fontSet);
	__glcFree(This);
	return NULL;
      }

      equal = FcPatternEqual(pattern, inMaster->pattern);
      FcPatternDestroy(pattern);
      if (equal) {
        FcCharSet* newCharSet = NULL;

#ifdef DEBUGMODE
        result = FcPatternGetCharSet(fontSet->fonts[i], FC_CHARSET, 0,
				     &charSet);
        assert(result != FcResultTypeMismatch);
#else
	FcPatternGetCharSet(fontSet->fonts[i], FC_CHARSET, 0, &charSet);
#endif

        newCharSet = FcCharSetUnion(This->charSet, charSet);
	if (!newCharSet) {
          __glcRaiseError(GLC_RESOURCE_ERROR);
          FcCharSetDestroy(This->charSet);
          FcFontSetDestroy(fontSet);
          __glcFree(This);
          return NULL;
	}

	FcCharSetDestroy(This->charSet);
	This->charSet = newCharSet;
      }
    }

    FcFontSetDestroy(fontSet);
  }

  /* The array 'map' will contain the actual character map */
  This->map = __glcArrayCreate(sizeof(__GLCcharMapElement));
  if (!This->map) {
    FcCharSetDestroy(This->charSet);
    __glcFree(This);
    return NULL;
  }

  return This;
}
Exemplo n.º 6
0
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr)
{
    if (!usrPtr)
        return 0;
    QFontDef fontDef = f;

    QFontEngineFT *engine;
    FontFile *fontfile = static_cast<FontFile *> (usrPtr);
    QFontEngine::FaceId fid;
    fid.filename = fontfile->fileName.toLocal8Bit();
    fid.index = fontfile->indexValue;

    //try and get the pattern
    FcPattern *pattern = FcPatternCreate();

    bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
    QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;

    engine = new QFontEngineFT(fontDef);

    FcValue value;
    value.type = FcTypeString;
        QByteArray cs = fontDef.family.toUtf8();
    value.u.s = (const FcChar8 *)cs.data();
    FcPatternAdd(pattern,FC_FAMILY,value,true);


    value.u.s = (const FcChar8 *)fid.filename.data();
    FcPatternAdd(pattern,FC_FILE,value,true);

    value.type = FcTypeInteger;
    value.u.i = fid.index;
    FcPatternAdd(pattern,FC_INDEX,value,true);

    QFontEngineFT::HintStyle default_hint_style;

    if (FcConfigSubstitute(0,pattern,FcMatchPattern)) {

        //hinting
        int hint_style = 0;
        if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch)
            hint_style = QFontEngineFT::HintFull;
        switch (hint_style) {
        case FC_HINT_NONE:
            default_hint_style = QFontEngineFT::HintNone;
            break;
        case FC_HINT_SLIGHT:
            default_hint_style = QFontEngineFT::HintLight;
            break;
        case FC_HINT_MEDIUM:
            default_hint_style = QFontEngineFT::HintMedium;
            break;
        default:
            default_hint_style = QFontEngineFT::HintFull;
            break;
        }
    }

    engine->setDefaultHintStyle(default_hint_style);
    if (!engine->init(fid,antialias,format)) {
        delete engine;
        engine = 0;
        return engine;
    }
    if (engine->invalid()) {
        delete engine;
        engine = 0;
    } else if (scriptRequiresOpenType(script)) {
        HB_Face hbFace = engine->harfbuzzFace();
        if (!hbFace || !hbFace->supported_scripts[script]) {
            delete engine;
            engine = 0;
        }
    }

    return engine;
}
Exemplo n.º 7
0
std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
{
    // The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm)
    // says that we must find an exact match for font family, slant (italic or oblique can be used)
    // and font weight (we only match bold/non-bold here).
    RefPtr<FcPattern> pattern = adoptRef(FcPatternCreate());
    // Never choose unscalable fonts, as they pixelate when displayed at different sizes.
    FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
    String familyNameString(getFamilyNameStringFromFamily(family));
    if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.utf8().data())))
        return nullptr;

    bool italic = fontDescription.italic();
    if (!FcPatternAddInteger(pattern.get(), FC_SLANT, italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN))
        return nullptr;
    if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, fontWeightToFontconfigWeight(fontDescription.weight())))
        return nullptr;
    if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fontDescription.computedPixelSize()))
        return nullptr;

    // The strategy is originally from Skia (src/ports/SkFontHost_fontconfig.cpp):
    //
    // We do not normally allow fontconfig to substitute one font family for another, since this
    // would break CSS font family fallback: the website should be in control of fallback. During
    // normal font matching, the only font family substitution permitted is for generic families
    // (sans, serif, monospace) or for strongly-aliased fonts (which are to be treated as
    // effectively identical). This is because the font matching step is designed to always find a
    // match for the font, which we don't want.
    //
    // Fontconfig is used in two stages: (1) configuration and (2) matching. During the
    // configuration step, before any matching occurs, we allow arbitrary family substitutions,
    // since this is an exact matter of respecting the user's font configuration.
    FcConfigSubstitute(nullptr, pattern.get(), FcMatchPattern);
    FcDefaultSubstitute(pattern.get());

    FcChar8* fontConfigFamilyNameAfterConfiguration;
    FcPatternGetString(pattern.get(), FC_FAMILY, 0, &fontConfigFamilyNameAfterConfiguration);
    String familyNameAfterConfiguration = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterConfiguration));

    FcResult fontConfigResult;
    RefPtr<FcPattern> resultPattern = adoptRef(FcFontMatch(nullptr, pattern.get(), &fontConfigResult));
    if (!resultPattern) // No match.
        return nullptr;

    FcChar8* fontConfigFamilyNameAfterMatching;
    FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &fontConfigFamilyNameAfterMatching);
    String familyNameAfterMatching = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterMatching));

    // If Fontconfig gave us a different font family than the one we requested, we should ignore it
    // and allow WebCore to give us the next font on the CSS fallback list. The exceptions are if
    // this family name is a commonly-used generic family, or if the families are strongly-aliased.
    // Checking for a strong alias comes last, since it is slow.
    if (!equalIgnoringCase(familyNameAfterConfiguration, familyNameAfterMatching)
        && !(equalIgnoringCase(familyNameString, "sans") || equalIgnoringCase(familyNameString, "sans-serif")
          || equalIgnoringCase(familyNameString, "serif") || equalIgnoringCase(familyNameString, "monospace")
          || equalIgnoringCase(familyNameString, "fantasy") || equalIgnoringCase(familyNameString, "cursive"))
        && !areStronglyAliased(familyNameAfterConfiguration, familyNameAfterMatching))
        return nullptr;

    // Verify that this font has an encoding compatible with Fontconfig. Fontconfig currently
    // supports three encodings in FcFreeTypeCharIndex: Unicode, Symbol and AppleRoman.
    // If this font doesn't have one of these three encodings, don't select it.
    auto platformData = std::make_unique<FontPlatformData>(resultPattern.get(), fontDescription);
    if (!platformData->hasCompatibleCharmap())
        return nullptr;

    return platformData;
}
Exemplo n.º 8
0
static FcBool
FcListAppend (FcListHashTable	*table,
	      FcPattern		*font,
	      FcObjectSet	*os,
	      const FcChar8	*lang)
{
    int		    o;
    FcPatternElt    *e;
    FcValueListPtr  v;
    FcChar32	    hash;
    FcListBucket    **prev, *bucket;
    int             familyidx = -1;
    int             fullnameidx = -1;
    int             styleidx = -1;
    int             defidx = 0;
    int             idx;

    hash = FcListPatternHash (font, os);
    for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
	 (bucket = *prev); prev = &(bucket->next))
    {
	if (bucket->hash == hash &&
	    FcListPatternEqual (bucket->pattern, font, os))
	    return FcTrue;
    }
    bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
    if (!bucket)
	goto bail0;
    bucket->next = 0;
    bucket->hash = hash;
    bucket->pattern = FcPatternCreate ();
    if (!bucket->pattern)
	goto bail1;

    for (o = 0; o < os->nobject; o++)
    {
	if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG))
	{
	    if (familyidx < 0)
		familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang);
	    defidx = familyidx;
	}
	else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG))
	{
	    if (fullnameidx < 0)
		fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang);
	    defidx = fullnameidx;
	}
	else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG))
	{
	    if (styleidx < 0)
		styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang);
	    defidx = styleidx;
	}
	else
	    defidx = 0;

	e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o]));
	if (e)
	{
	    for (v = FcPatternEltValues(e), idx = 0; v;
		 v = FcValueListNext(v), ++idx)
	    {
		if (!FcPatternAdd (bucket->pattern,
				   os->objects[o],
				   FcValueCanonicalize(&v->value), defidx != idx))
		    goto bail2;
	    }
	}
    }
    *prev = bucket;
    ++table->entries;

    return FcTrue;

bail2:
    FcPatternDestroy (bucket->pattern);
bail1:
    free (bucket);
bail0:
    return FcFalse;
}
Exemplo n.º 9
0
FontInfo *
get_font_info_list (int *num)
{
	FcInit();
	*num = -1;
	FcPattern *pat = FcPatternCreate();
	if (!pat) {
		fprintf(stderr, "Create FcPattern Failed\n");
		return NULL;
	}

	FcObjectSet *os = FcObjectSetBuild(
	                      FC_FAMILY,
	                      FC_FAMILYLANG,
	                      FC_STYLE,
	                      FC_FILE,
	                      FC_LANG,
	                      FC_SPACING,
	                      NULL);
	if (!os) {
		fprintf(stderr, "Build FcObjectSet Failed\n");
		FcPatternDestroy(pat);
		return NULL;
	}

	FcFontSet *fs = FcFontList(0, pat, os);
	FcObjectSetDestroy(os);
	FcPatternDestroy(pat);
	if (!fs) {
		fprintf(stderr, "List Font Failed\n");
		return NULL;
	}

	int i;
	int cnt = 0;
	FontInfo *list = NULL;
	for (i = 0; i < fs->nfont; i++) {
		FontInfo *info = calloc(1, sizeof(FontInfo));
		if (!info) {
			fprintf(stderr, "Alloc memory failed");
			continue;
		}

		info->family = (char*)FcPatternFormat(fs->fonts[i],
		                                      (FcChar8*)"%{family}");
		info->familylang = (char*)FcPatternFormat(fs->fonts[i],
		                   (FcChar8*)"%{familylang}");
		info->style = (char*)FcPatternFormat(fs->fonts[i],
		                                     (FcChar8*)"%{style}");
		info->filename = (char*)FcPatternFormat(fs->fonts[i],
		                                        (FcChar8*)"%{file}");
		info->lang = (char*)FcPatternFormat(fs->fonts[i],
		                                    (FcChar8*)"%{lang}");
		info->spacing = (char*)FcPatternFormat(fs->fonts[i],
		                                       (FcChar8*)"%{spacing}");
		if (!info->family || !info->familylang ||
		        !info->style || !info->filename ||
		        !info->lang || !info->spacing) {
			font_info_free(info);
			continue;
		}

		FontInfo *tmp = malloc((cnt+1) * sizeof(FontInfo));
		if (!tmp) {
			fprintf(stderr, "Alloc memory failed\n");
			font_info_free(info);
			continue;
		}

		memcpy(tmp+cnt, info, sizeof(FontInfo));
		free(info);
		if (cnt != 0 ) {
			memcpy(tmp, list, cnt * sizeof(FontInfo));
			free(list);
			list = NULL;
		}

		list = tmp;
		tmp = NULL;

		cnt++;
	}
	FcFontSetDestroy(fs);
	FcFini(); // Error: FcCacheFini

	*num = cnt;

	return list;
}
Exemplo n.º 10
0
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, const char *str)
{
	if (!FcInit()) return false;

	bool ret = false;

	/* Fontconfig doesn't handle full language isocodes, only the part
	 * before the _ of e.g. en_GB is used, so "remove" everything after
	 * the _. */
	char lang[16];
	strecpy(lang, language_isocode, lastof(lang));
	char *split = strchr(lang, '_');
	if (split != NULL) *split = '\0';

	FcPattern *pat;
	FcPattern *match;
	FcResult result;
	FcChar8 *file;
	FcFontSet *fs;
	FcValue val;
	val.type = FcTypeString;
	val.u.s = (FcChar8*)lang;

	/* First create a pattern to match the wanted language */
	pat = FcPatternCreate();
	/* And fill it with the language and other defaults */
	if (pat == NULL ||
			!FcPatternAdd(pat, "lang", val, false) ||
			!FcConfigSubstitute(0, pat, FcMatchPattern)) {
		goto error_pattern;
	}

	FcDefaultSubstitute(pat);

	/* Then create a font set and match that */
	match = FcFontMatch(0, pat, &result);

	if (match == NULL) {
		goto error_pattern;
	}

	/* Find all fonts that do match */
	fs = FcFontSetCreate();
	FcFontSetAdd(fs, match);

	/* And take the first, if it exists */
	if (fs->nfont <= 0 || FcPatternGetString(fs->fonts[0], FC_FILE, 0, &file)) {
		goto error_fontset;
	}

	strecpy(settings->small_font,  (const char*)file, lastof(settings->small_font));
	strecpy(settings->medium_font, (const char*)file, lastof(settings->medium_font));
	strecpy(settings->large_font,  (const char*)file, lastof(settings->large_font));

	ret = true;

error_fontset:
	FcFontSetDestroy(fs);
error_pattern:
	if (pat != NULL) FcPatternDestroy(pat);
	FcFini();
	return ret;
}
Exemplo n.º 11
0
int face_from_options(lua_State* L) {
  FT_Face face;
  FcChar8 * font_path;
  FcPattern* p;
  FcPattern* matched;
  FcResult result;
  int index = 0;

  const char *family = "Gentium";
  double pointSize = 12;
  int slant = FC_SLANT_ROMAN;
  int weight = 100;
  const char *script = "latin";
  const char *language = "eng";
  int direction = HB_DIRECTION_LTR;

  if (!lua_istable(L, 1)) return 0;

  lua_pushstring(L, "font");
  lua_gettable(L, -2);
  if (lua_isstring(L, -1)) { family = lua_tostring(L, -1); }
  lua_pop(L,1);

  lua_pushstring(L, "weight");
  lua_gettable(L, -2);
  if (lua_isnumber(L, -1)) {
    int newWeight = lua_tointeger(L, -1);
    if      (newWeight <= 100) newWeight = FC_WEIGHT_THIN;
    else if (newWeight <= 200) newWeight = FC_WEIGHT_ULTRALIGHT;
    else if (newWeight <= 300) newWeight = FC_WEIGHT_LIGHT;
    else if (newWeight <= 400) newWeight = FC_WEIGHT_NORMAL;
    else if (newWeight <= 500) newWeight = FC_WEIGHT_MEDIUM;
    else if (newWeight <= 600) newWeight = FC_WEIGHT_DEMIBOLD;
    else if (newWeight <= 700) newWeight = FC_WEIGHT_BOLD;
    else if (newWeight <= 800) newWeight = FC_WEIGHT_ULTRABOLD;
    else                       newWeight = FC_WEIGHT_HEAVY;
    weight = newWeight;
  }
  lua_pop(L,1);

  lua_pushstring(L, "size");
  lua_gettable(L, -2);
  if (lua_isnumber(L, -1)) { pointSize = lua_tonumber(L, -1); }
  lua_pop(L,1);

  lua_pushstring(L, "language");
  lua_gettable(L, -2);
  if (lua_isstring(L, -1)) { language = lua_tostring(L, -1); }
  lua_pop(L,1);

  lua_pushstring(L, "style");
  lua_gettable(L, -2);
  if (lua_isstring(L, -1)) {
    const char* newStyleAsText = lua_tostring(L, -1);
    if (!strcmp(newStyleAsText, "italic"))
      slant = FC_SLANT_ITALIC;
  }
  lua_pop(L,1);

  p = FcPatternCreate();

  FcPatternAddString (p, FC_FAMILY, (FcChar8*)(family));
  FcPatternAddDouble (p, FC_SIZE, pointSize);
  FcPatternAddInteger(p, FC_SLANT, slant);
  FcPatternAddInteger(p, FC_WEIGHT, weight);

  // /* Add fallback fonts here. Some of the standard 14 should be fine. */
  FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Times-Roman");
  FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Times");
  FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Helvetica");
  matched = FcFontMatch (0, p, &result);
  
  if (FcPatternGetString (matched, FC_FILE, 0, &font_path) != FcResultMatch)
    return 0;
  
  FcPatternGetInteger(matched, FC_INDEX, 0, &index);
  font_path = (FcChar8 *)strdup((char*)font_path); /* XXX signedness problems? */
  if (!font_path) {
    printf("Finding font path failed\n");
    return 0;
  }
  /* Push back slant and weight, we need to pass them to libpdftex */
  FcPatternGetInteger(matched, FC_SLANT, 0, &slant);
  FcPatternGetInteger(matched, FC_WEIGHT, 0, &weight);

  /* Find out which family we did actually pick up */
  if (FcPatternGetString (matched, FC_FAMILY, 0, &family) != FcResultMatch)
    return 0;
  lua_newtable(L);
  lua_pushstring(L, "filename");
  lua_pushstring(L, (char*)font_path);
  lua_settable(L, -3);

  lua_pushstring(L, "family");
  lua_pushstring(L, (char*)(family));
  lua_settable(L, -3);

  FcPatternDestroy (matched);
  FcPatternDestroy (p);

  face = (FT_Face)malloc(sizeof(FT_Face));
  if (FT_New_Face(ft_library, (char*)font_path, index, &face))
    return 0;

  if (FT_Set_Char_Size(face,pointSize * 64.0, 0, 0, 0))
    return 0;

  lua_pushstring(L, "index");
  lua_pushinteger(L, index);
  lua_settable(L, -3);

  lua_pushstring(L, "pointsize");
  lua_pushnumber(L, pointSize);
  lua_settable(L, -3);

  lua_pushstring(L, "face");
  lua_pushlightuserdata(L, face);
  lua_settable(L, -3);

  return 1;
}
Exemplo n.º 12
0
const vlc_family_t *FontConfig_GetFamily( filter_t *p_filter, const char *psz_family )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    char *psz_lc = ToLower( psz_family );

    if( unlikely( !psz_lc ) )
        return NULL;

    vlc_family_t *p_family =
            vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc );

    if( p_family != kVLCDictionaryNotFound )
    {
        free( psz_lc );
        return p_family;
    }

    p_family = NewFamily( p_filter, psz_lc, &p_sys->p_families,
                          &p_sys->family_map, psz_lc );

    free( psz_lc );
    if( !p_family )
        return NULL;

    bool b_bold, b_italic;

    for( int i = 0; i < 4; ++i )
    {
        switch( i )
        {
        case 0:
            b_bold = false;
            b_italic = false;
            break;
        case 1:
            b_bold = true;
            b_italic = false;
            break;
        case 2:
            b_bold = false;
            b_italic = true;
            break;
        case 3:
            b_bold = true;
            b_italic = true;
            break;
        }

        int i_index = 0;
        FcResult result = FcResultMatch;
        FcPattern *pat, *p_pat;
        FcChar8* val_s;
        FcBool val_b;
        char *psz_fontfile = NULL;
        FcConfig* config = NULL;

        /* Create a pattern and fill it */
        pat = FcPatternCreate();
        if (!pat) continue;

        /* */
        FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_family );
        FcPatternAddBool( pat, FC_OUTLINE, FcTrue );
        FcPatternAddInteger( pat, FC_SLANT, b_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN );
        FcPatternAddInteger( pat, FC_WEIGHT, b_bold ? FC_WEIGHT_EXTRABOLD : FC_WEIGHT_NORMAL );

        /* */
        FcDefaultSubstitute( pat );
        if( !FcConfigSubstitute( config, pat, FcMatchPattern ) )
        {
            FcPatternDestroy( pat );
            continue;
        }

        /* Find the best font for the pattern, destroy the pattern */
        p_pat = FcFontMatch( config, pat, &result );
        FcPatternDestroy( pat );
        if( !p_pat || result == FcResultNoMatch ) continue;

        /* Check the new pattern */
        if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) )
            || ( val_b != FcTrue ) )
        {
            FcPatternDestroy( p_pat );
            continue;
        }
        if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) )
        {
            i_index = 0;
        }

        if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) )
        {
            FcPatternDestroy( p_pat );
            continue;
        }

        if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) )
            psz_fontfile = strdup( (const char*)val_s );

        FcPatternDestroy( p_pat );

        if( !psz_fontfile )
            continue;

        NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family );
    }

    return p_family;
}
Exemplo n.º 13
0
vlc_family_t *FontConfig_GetFallbacks( filter_t *p_filter, const char *psz_family,
                                       uni_char_t codepoint )
{

    VLC_UNUSED( codepoint );

    vlc_family_t *p_family = NULL;
    filter_sys_t *p_sys    = p_filter->p_sys;

    char *psz_lc = ToLower( psz_family );

    if( unlikely( !psz_lc ) )
        return NULL;

    p_family = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc );

    if( p_family != kVLCDictionaryNotFound )
    {
        free( psz_lc );
        return p_family;
    }
    else
        p_family = NULL;

    const char *psz_last_name = "";
    FcPattern  *p_pattern = FcPatternCreate();
    FcValue     family;
    family.type = FcTypeString;
    family.u.s = ( const FcChar8* ) psz_family;
    FcPatternAdd( p_pattern, FC_FAMILY, family, FcFalse );
    if( FcConfigSubstitute( NULL, p_pattern, FcMatchPattern ) == FcTrue )
    {
        FcDefaultSubstitute( p_pattern );
        FcResult result;
        FcFontSet* p_font_set = FcFontSort( NULL, p_pattern, FcTrue, NULL, &result );
        if( p_font_set )
        {
            for( int i = 0; i < p_font_set->nfont; ++i )
            {
                char* psz_name = NULL;
                FcPatternGetString( p_font_set->fonts[i],
                                    FC_FAMILY, 0, ( FcChar8** )( &psz_name ) );

                /* Avoid duplicate family names */
                if( strcasecmp( psz_last_name, psz_name ) )
                {
                    vlc_family_t *p_temp = NewFamily( p_filter, psz_name,
                                                      &p_family, NULL, NULL );

                    if( unlikely( !p_temp ) )
                    {
                        FcFontSetDestroy( p_font_set );
                        FcPatternDestroy( p_pattern );
                        if( p_family )
                            FreeFamilies( p_family, NULL );
                        free( psz_lc );
                        return NULL;
                    }

                    psz_last_name = p_temp->psz_name;
                }
            }
            FcFontSetDestroy( p_font_set );
        }
    }
    FcPatternDestroy( p_pattern );

    if( p_family )
        vlc_dictionary_insert( &p_sys->fallback_map, psz_lc, p_family );

    free( psz_lc );
    return p_family;
}
Exemplo n.º 14
0
static void
apply_xft_settings (struct x_display_info *dpyinfo,
                    struct xsettings *settings)
{
#ifdef HAVE_XFT
  FcPattern *pat;
  struct xsettings oldsettings;
  bool changed = false;

  memset (&oldsettings, 0, sizeof (oldsettings));
  pat = FcPatternCreate ();
  XftDefaultSubstitute (dpyinfo->display,
                        XScreenNumberOfScreen (dpyinfo->screen),
                        pat);
  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa);
  FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting);
#ifdef FC_HINT_STYLE
  FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle);
#endif
  FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter);
  FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba);
  FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi);

  if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa)
    {
      FcPatternDel (pat, FC_ANTIALIAS);
      FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa);
      changed = true;
      oldsettings.aa = settings->aa;
    }

  if ((settings->seen & SEEN_HINTING) != 0
      && oldsettings.hinting != settings->hinting)
    {
      FcPatternDel (pat, FC_HINTING);
      FcPatternAddBool (pat, FC_HINTING, settings->hinting);
      changed = true;
      oldsettings.hinting = settings->hinting;
    }
  if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba)
    {
      FcPatternDel (pat, FC_RGBA);
      FcPatternAddInteger (pat, FC_RGBA, settings->rgba);
      oldsettings.rgba = settings->rgba;
      changed = true;
    }

  /* Older fontconfig versions don't have FC_LCD_FILTER. */
  if ((settings->seen & SEEN_LCDFILTER) != 0
      && oldsettings.lcdfilter != settings->lcdfilter)
    {
      FcPatternDel (pat, FC_LCD_FILTER);
      FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter);
      changed = true;
      oldsettings.lcdfilter = settings->lcdfilter;
    }

#ifdef FC_HINT_STYLE
  if ((settings->seen & SEEN_HINTSTYLE) != 0
      && oldsettings.hintstyle != settings->hintstyle)
    {
      FcPatternDel (pat, FC_HINT_STYLE);
      FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle);
      changed = true;
      oldsettings.hintstyle = settings->hintstyle;
    }
#endif

  if ((settings->seen & SEEN_DPI) != 0 && oldsettings.dpi != settings->dpi
      && settings->dpi > 0)
    {
      FcPatternDel (pat, FC_DPI);
      FcPatternAddDouble (pat, FC_DPI, settings->dpi);
      changed = true;
      oldsettings.dpi = settings->dpi;

      /* Changing the DPI on this display affects all frames on it.
	 Check FRAME_RES_X and FRAME_RES_Y in frame.h to see how.  */
      dpyinfo->resy = dpyinfo->resx = settings->dpi;
    }

  if (changed)
    {
      static char const format[] =
	"Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, "
	"Hintstyle: %d, DPI: %f";
      enum
      {
	d_formats = 5,
	d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d",
	lf_formats = 1,
	max_f_integer_digits = DBL_MAX_10_EXP + 1,
	f_precision = 6,
	lf_growth = (sizeof "-." + max_f_integer_digits + f_precision
		     - sizeof "%f")
      };
      char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];

      XftDefaultSet (dpyinfo->display, pat);
      store_config_changed_event (Qfont_render,
				  XCAR (dpyinfo->name_list_element));
      Vxft_settings
	= make_formatted_string (buf, format,
				 oldsettings.aa, oldsettings.hinting,
				 oldsettings.rgba, oldsettings.lcdfilter,
				 oldsettings.hintstyle, oldsettings.dpi);

    }
  else
    FcPatternDestroy (pat);
#endif /* HAVE_XFT */
}
Exemplo n.º 15
0
void WebFontInfo::renderStyleForStrike(const char* family, int sizeAndStyle, WebFontRenderStyle* out)
{
    bool isBold = sizeAndStyle & 1;
    bool isItalic = sizeAndStyle & 2;
    int pixelSize = sizeAndStyle >> 2;

    FcPattern* pattern = FcPatternCreate();
    FcValue fcvalue;

    fcvalue.type = FcTypeString;
    fcvalue.u.s = reinterpret_cast<const FcChar8 *>(family);
    FcPatternAdd(pattern, FC_FAMILY, fcvalue, FcFalse);

    fcvalue.type = FcTypeInteger;
    fcvalue.u.i = isBold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL;
    FcPatternAdd(pattern, FC_WEIGHT, fcvalue, FcFalse);

    fcvalue.type = FcTypeInteger;
    fcvalue.u.i = isItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
    FcPatternAdd(pattern, FC_SLANT, fcvalue, FcFalse);

    fcvalue.type = FcTypeBool;
    fcvalue.u.b = FcTrue;
    FcPatternAdd(pattern, FC_SCALABLE, fcvalue, FcFalse);

    fcvalue.type = FcTypeDouble;
    fcvalue.u.d = pixelSize;
    FcPatternAdd(pattern, FC_SIZE, fcvalue, FcFalse);

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult result;
    // Some versions of fontconfig don't actually write a value into result.
    // However, it's not clear from the documentation if result should be a
    // non-0 pointer: future versions might expect to be able to write to
    // it. So we pass in a valid pointer and ignore it.
    FcPattern* match = FcFontMatch(0, pattern, &result);
    FcPatternDestroy(pattern);

    out->setDefaults();

    if (!match)
        return;

    FcBool b;
    int i;

    if (FcPatternGetBool(match, FC_ANTIALIAS, 0, &b) == FcResultMatch)
        out->useAntiAlias = b;
    if (FcPatternGetBool(match, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch)
        out->useBitmaps = b;
    if (FcPatternGetBool(match, FC_AUTOHINT, 0, &b) == FcResultMatch)
        out->useAutoHint = b;
    if (FcPatternGetBool(match, FC_HINTING, 0, &b) == FcResultMatch)
        out->useHinting = b;
    if (FcPatternGetInteger(match, FC_HINT_STYLE, 0, &i) == FcResultMatch)
        out->hintStyle = i;
    if (FcPatternGetInteger(match, FC_RGBA, 0, &i) == FcResultMatch) {
        switch (i) {
        case FC_RGBA_NONE:
            out->useSubpixelRendering = 0;
            break;
        case FC_RGBA_RGB:
        case FC_RGBA_BGR:
        case FC_RGBA_VRGB:
        case FC_RGBA_VBGR:
            out->useSubpixelRendering = 1;
            break;
        default:
            // This includes FC_RGBA_UNKNOWN.
            out->useSubpixelRendering = 2;
            break;
        }
    }

    // FontConfig doesn't provide parameters to configure whether subpixel
    // positioning should be used or not, so we just use a global setting.
    out->useSubpixelPositioning = useSubpixelPositioning;

    FcPatternDestroy(match);
}
Exemplo n.º 16
0
static void
apply_xft_settings (struct x_display_info *dpyinfo,
                    struct xsettings *settings)
{
#ifdef HAVE_XFT
  FcPattern *pat;
  struct xsettings oldsettings;
  bool changed = false;

  memset (&oldsettings, 0, sizeof (oldsettings));
  pat = FcPatternCreate ();
  XftDefaultSubstitute (dpyinfo->display,
                        XScreenNumberOfScreen (dpyinfo->screen),
                        pat);
  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa);
  FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting);
#ifdef FC_HINT_STYLE
  FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle);
#endif
  FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter);
  FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba);
  FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi);

  if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa)
    {
      FcPatternDel (pat, FC_ANTIALIAS);
      FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa);
      changed = true;
      oldsettings.aa = settings->aa;
    }

  if ((settings->seen & SEEN_HINTING) != 0
      && oldsettings.hinting != settings->hinting)
    {
      FcPatternDel (pat, FC_HINTING);
      FcPatternAddBool (pat, FC_HINTING, settings->hinting);
      changed = true;
      oldsettings.hinting = settings->hinting;
    }
  if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba)
    {
      FcPatternDel (pat, FC_RGBA);
      FcPatternAddInteger (pat, FC_RGBA, settings->rgba);
      oldsettings.rgba = settings->rgba;
      changed = true;
    }

  /* Older fontconfig versions don't have FC_LCD_FILTER. */
  if ((settings->seen & SEEN_LCDFILTER) != 0
      && oldsettings.lcdfilter != settings->lcdfilter)
    {
      FcPatternDel (pat, FC_LCD_FILTER);
      FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter);
      changed = true;
      oldsettings.lcdfilter = settings->lcdfilter;
    }

#ifdef FC_HINT_STYLE
  if ((settings->seen & SEEN_HINTSTYLE) != 0
      && oldsettings.hintstyle != settings->hintstyle)
    {
      FcPatternDel (pat, FC_HINT_STYLE);
      FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle);
      changed = true;
      oldsettings.hintstyle = settings->hintstyle;
    }
#endif

  if ((settings->seen & SEEN_DPI) != 0
      && settings->dpi > 0
      /* The following conjunct avoids setting `changed' to true when
	 old and new dpi settings do not differ "substantially".
	 Otherwise, the dynamic-setting Elisp code may process all sorts
	 of unrelated settings that override users' font customizations,
	 among others.  Compare:

	 https://lists.gnu.org/r/emacs-devel/2016-05/msg00557.html
	 https://lists.gnu.org/r/bug-gnu-emacs/2016-12/msg00820.html

	 As soon as the dynamic-settings code has been tested and
	 verified, this Emacs 25.2 workaround should be removed.  */
      && ((oldsettings.dpi >= settings->dpi
	   && (oldsettings.dpi - settings->dpi) > 2)
	  || ((settings->dpi > oldsettings.dpi)
	      && (settings->dpi - oldsettings.dpi) > 2)))
    {
      FcPatternDel (pat, FC_DPI);
      FcPatternAddDouble (pat, FC_DPI, settings->dpi);
      changed = true;
      oldsettings.dpi = settings->dpi;

      /* Changing the DPI on this display affects all frames on it.
	 Check FRAME_RES_X and FRAME_RES_Y in frame.h to see how.  */
      dpyinfo->resy = dpyinfo->resx = settings->dpi;
    }

  if (changed)
    {
      static char const format[] =
	"Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, "
	"Hintstyle: %d, DPI: %f";
      enum
      {
	d_formats = 5,
	d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d",
	lf_formats = 1,
	max_f_integer_digits = DBL_MAX_10_EXP + 1,
	f_precision = 6,
	lf_growth = (sizeof "-." + max_f_integer_digits + f_precision
		     - sizeof "%f")
      };
      char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];

      XftDefaultSet (dpyinfo->display, pat);
      store_config_changed_event (Qfont_render,
				  XCAR (dpyinfo->name_list_element));
      Vxft_settings
	= make_formatted_string (buf, format,
				 oldsettings.aa, oldsettings.hinting,
				 oldsettings.rgba, oldsettings.lcdfilter,
				 oldsettings.hintstyle, oldsettings.dpi);

    }
  else
    FcPatternDestroy (pat);
#endif /* HAVE_XFT */
}
Exemplo n.º 17
0
void QFontconfigDatabase::populateFontDatabase()
{
    FcFontSet  *fonts;

    QString familyName;
    FcChar8 *value = 0;
    int weight_value;
    int slant_value;
    int spacing_value;
    FcChar8 *file_value;
    int indexValue;
    FcChar8 *foundry_value;
    FcBool scalable;
    FcBool antialias;

    {
        FcObjectSet *os = FcObjectSetCreate();
        FcPattern *pattern = FcPatternCreate();
        const char *properties [] = {
            FC_FAMILY, FC_WEIGHT, FC_SLANT,
            FC_SPACING, FC_FILE, FC_INDEX,
            FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
            FC_WIDTH,
#if FC_VERSION >= 20297
            FC_CAPABILITY,
#endif
            (const char *)0
        };
        const char **p = properties;
        while (*p) {
            FcObjectSetAdd(os, *p);
            ++p;
        }
        fonts = FcFontList(0, pattern, os);
        FcObjectSetDestroy(os);
        FcPatternDestroy(pattern);
    }

    for (int i = 0; i < fonts->nfont; i++) {
        if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
            continue;
        //         capitalize(value);
        familyName = QString::fromUtf8((const char *)value);
        slant_value = FC_SLANT_ROMAN;
        weight_value = FC_WEIGHT_MEDIUM;
        spacing_value = FC_PROPORTIONAL;
        file_value = 0;
        indexValue = 0;
        scalable = FcTrue;


        if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch)
            slant_value = FC_SLANT_ROMAN;
        if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch)
            weight_value = FC_WEIGHT_MEDIUM;
        if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch)
            spacing_value = FC_PROPORTIONAL;
        if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch)
            file_value = 0;
        if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch)
            indexValue = 0;
        if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch)
            scalable = FcTrue;
        if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
            foundry_value = 0;
        if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch)
            antialias = true;

        QSupportedWritingSystems writingSystems;
        FcLangSet *langset = 0;
        FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset);
        if (res == FcResultMatch) {
            for (int i = 1; i < LanguageCount; ++i) {
                const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i];
                if (lang) {
                    FcLangResult langRes = FcLangSetHasLang(langset, lang);
                    if (langRes != FcLangDifferentLang)
                        writingSystems.setSupported(QFontDatabase::WritingSystem(i));
                }
            }
        } else {
            // we set Other to supported for symbol fonts. It makes no
            // sense to merge these with other ones, as they are
            // special in a way.
            writingSystems.setSupported(QFontDatabase::Other);
        }

        FcCharSet *cs = 0;
        res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs);
        if (res == FcResultMatch) {
            // some languages are not supported by FontConfig, we rather check the
            // charset to detect these
            for (int i = 1; i < SampleCharCount; ++i) {
                if (!sampleCharForWritingSystem[i])
                    continue;
                if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i]))
                    writingSystems.setSupported(QFontDatabase::WritingSystem(i));
            }
        }

#if FC_VERSION >= 20297
        for (int j = 1; j < LanguageCount; ++j) {
            if (writingSystems.supported(QFontDatabase::WritingSystem(j))
                && requiresOpenType(j) && openType[j]) {
                FcChar8 *cap;
                res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap);
                if (res != FcResultMatch || !strstr((const char *)cap, openType[j]))
                    writingSystems.setSupported(QFontDatabase::WritingSystem(j),false);
            }
        }
#endif

        FontFile *fontFile = new FontFile;
        fontFile->fileName = QLatin1String((const char *)file_value);
        fontFile->indexValue = indexValue;

        QFont::Style style = (slant_value == FC_SLANT_ITALIC)
                         ? QFont::StyleItalic
                         : ((slant_value == FC_SLANT_OBLIQUE)
                            ? QFont::StyleOblique
                            : QFont::StyleNormal);
        QFont::Weight weight = QFont::Weight(getFCWeight(weight_value));

        double pixel_size = 0;
        if (!scalable)
            FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size);

        int width = FC_WIDTH_NORMAL;
        FcPatternGetInteger(fonts->fonts[i], FC_WIDTH, 0, &width);

        QFont::Stretch stretch;
        switch (width) {
        case FC_WIDTH_ULTRACONDENSED: stretch = QFont::UltraCondensed; break;
        case FC_WIDTH_EXTRACONDENSED: stretch = QFont::ExtraCondensed; break;
        case FC_WIDTH_CONDENSED:      stretch = QFont::Condensed;      break;
        case FC_WIDTH_SEMICONDENSED:  stretch = QFont::SemiCondensed;  break;
        case FC_WIDTH_NORMAL:         stretch = QFont::Unstretched;    break;
        case FC_WIDTH_SEMIEXPANDED:   stretch = QFont::SemiExpanded;   break;
        case FC_WIDTH_EXPANDED:       stretch = QFont::Expanded;       break;
        case FC_WIDTH_EXTRAEXPANDED:  stretch = QFont::ExtraExpanded;  break;
        case FC_WIDTH_ULTRAEXPANDED:  stretch = QFont::UltraExpanded;  break;
        default:                      stretch = QFont::Unstretched;    break;
        }

        QPlatformFontDatabase::registerFont(familyName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,writingSystems,fontFile);
//        qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
    }

    FcFontSetDestroy (fonts);

    struct FcDefaultFont {
        const char *qtname;
        const char *rawname;
        bool fixed;
    };
    const FcDefaultFont defaults[] = {
        { "Serif", "serif", false },
        { "Sans Serif", "sans-serif", false },
        { "Monospace", "monospace", true },
        { 0, 0, false }
    };
    const FcDefaultFont *f = defaults;
    // aliases only make sense for 'common', not for any of the specials
    QSupportedWritingSystems ws;
    ws.setSupported(QFontDatabase::Latin);


    while (f->qtname) {
        registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,ws,0);
        registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,ws,0);
        registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,ws,0);
        ++f;
    }

    //Lighthouse has very lazy population of the font db. We want it to be initialized when
    //QApplication is constructed, so that the population procedure can do something like this to
    //set the default font
//    const FcDefaultFont *s = defaults;
//    QFont font("Sans Serif");
//    font.setPointSize(9);
//    QApplication::setFont(font);
}
Exemplo n.º 18
0
CAMLprim value pattern_make(value props)
{
  CAMLparam0();
  CAMLreturn(caml_box_fcpattern(FcPatternCreate()));
}
Exemplo n.º 19
0
static cairo_status_t
create_scaled_font (cairo_t * cr,
		    cairo_scaled_font_t **out)
{
    FcPattern *pattern, *resolved;
    FcResult result;
    cairo_font_face_t *font_face;
    cairo_scaled_font_t *scaled_font;
    cairo_font_options_t *font_options;
    cairo_matrix_t font_matrix, ctm;
    cairo_status_t status;
    double pixel_size;

    font_options = cairo_font_options_create ();

    cairo_get_font_options (cr, font_options);

    pattern = FcPatternCreate ();
    if (pattern == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *)"Nimbus Sans L");
    FcPatternAddDouble (pattern, FC_PIXEL_SIZE, TEXT_SIZE);
    FcConfigSubstitute (NULL, pattern, FcMatchPattern);

    cairo_ft_font_options_substitute (font_options, pattern);

    FcDefaultSubstitute (pattern);
    resolved = FcFontMatch (NULL, pattern, &result);
    if (resolved == NULL) {
	FcPatternDestroy (pattern);
	return CAIRO_STATUS_NO_MEMORY;
    }

    /* set layout to vertical */
    FcPatternDel (resolved, FC_VERTICAL_LAYOUT);
    FcPatternAddBool (resolved, FC_VERTICAL_LAYOUT, FcTrue);

    FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size);

    font_face = cairo_ft_font_face_create_for_pattern (resolved);

    cairo_matrix_init_translate (&font_matrix, 10, 30);
    cairo_matrix_rotate (&font_matrix, M_PI_2/3);
    cairo_matrix_scale (&font_matrix, pixel_size, pixel_size);

    cairo_get_matrix (cr, &ctm);

    scaled_font = cairo_scaled_font_create (font_face,
					    &font_matrix,
					    &ctm,
					    font_options);

    cairo_font_options_destroy (font_options);
    cairo_font_face_destroy (font_face);
    FcPatternDestroy (pattern);
    FcPatternDestroy (resolved);

    status = cairo_scaled_font_status (scaled_font);
    if (status) {
	cairo_scaled_font_destroy (scaled_font);
	return status;
    }

    *out = scaled_font;
    return CAIRO_STATUS_SUCCESS;
}
Exemplo n.º 20
0
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_pattern(0)
    , m_size(fontDescription.computedSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_scaledFont(0)
    , m_face(0)
{
    FontPlatformData::init();

    CString familyNameString = familyName.string().utf8();
    const char* fcfamily = familyNameString.data();

    int fcslant = FC_SLANT_ROMAN;
    // FIXME: Map all FontWeight values to fontconfig weights.
    int fcweight = FC_WEIGHT_NORMAL;
    float fcsize = fontDescription.computedSize();
    if (fontDescription.italic())
        fcslant = FC_SLANT_ITALIC;
    if (fontDescription.weight() >= FontWeight600)
        fcweight = FC_WEIGHT_BOLD;

    FcConfig *config = FcConfigGetCurrent();

    //printf("family = %s\n", fcfamily);

    int type = fontDescription.genericFamily();

    FcPattern* pattern = FcPatternCreate();
    
    if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
        goto freePattern;

    switch (type) {
        case FontDescription::SerifFamily:
            fcfamily = "serif";
            break;
        case FontDescription::SansSerifFamily:
            fcfamily = "sans-serif";
            break;
        case FontDescription::MonospaceFamily:
            fcfamily = "monospace";
            break;
        case FontDescription::NoFamily:
        case FontDescription::StandardFamily:
        default:
            fcfamily = "sans-serif";
    }

    if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
        goto freePattern;
    if (!FcPatternAddInteger(pattern, FC_SLANT, fcslant))
        goto freePattern;
    if (!FcPatternAddInteger(pattern, FC_WEIGHT, fcweight))
        goto freePattern;
    if (!FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fcsize))
        goto freePattern;

    FcConfigSubstitute(config, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult fcresult;
    m_pattern = FcFontMatch(config, pattern, &fcresult);
    FcPatternReference(m_pattern);
    // FIXME: should we set some default font?
    if (!m_pattern)
        goto freePattern;

    FcChar8 *fc_filename;
    char *filename;
    int id;
    id = 0;

    if (FcPatternGetString(m_pattern, FC_FILE, 0, &fc_filename) != FcResultMatch) {
        DS_WAR("cannot retrieve font\n");
        goto freePattern;
    }

    filename = (char *) fc_filename; //use C cast as FcChar is a fontconfig type
    //printf("filename = %s\n", filename);

    if (FcPatternGetInteger(m_pattern, FC_INDEX, 0, &id) != FcResultMatch) {
        DS_WAR("cannot retrieve font index\n");
        goto freePattern;
    }
    
    if (FT_Error error = FT_New_Face(m_library, filename, id, &m_face)) {
    //if (FT_Error error = FT_New_Face(m_library, too, id, &m_face)) {
        DS_WAR("fail to open font" <<  filename << "with index " << id << " (error = 0x%x)\n" << error);
        m_face = 0;
        goto freePattern;
    }

    FT_Set_Pixel_Sizes(m_face, 0, static_cast<uint> (fontDescription.computedSize()));
    //DBGML(MODULE_FONTS, LEVEL_INFO, "open font %s with size %d\n", filename, static_cast<uint> (fontDescription.specifiedSize()));

freePattern:
    FcPatternDestroy(pattern);
    FcConfigDestroy(config);
}
int
main (int argc, char **argv)
{
    int			verbose = 0;
    int			sort = 0, all = 0;
    const FcChar8	*format = NULL;
    int			i;
    FcObjectSet		*os = 0;
    FcFontSet		*fs;
    FcPattern		*pat;
    FcResult		result;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int			c;

#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "asvf:Vh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "asvf:Vh")) != -1)
#endif
    {
	switch (c) {
	case 'a':
	    all = 1;
	    break;
	case 's':
	    sort = 1;
	    break;
	case 'v':
	    verbose = 1;
	    break;
	case 'f':
	    format = (FcChar8 *) strdup (optarg);
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (!FcInit ())
    {
	fprintf (stderr, "Can't init font config library\n");
	return 1;
    }
    if (argv[i])
    {
	pat = FcNameParse ((FcChar8 *) argv[i]);
	while (argv[++i])
	{
	    if (!os)
		os = FcObjectSetCreate ();
	    FcObjectSetAdd (os, argv[i]);
	}
    }
    else
	pat = FcPatternCreate ();

    if (!pat)
	return 1;

    FcConfigSubstitute (0, pat, FcMatchPattern);
    FcDefaultSubstitute (pat);
    
    fs = FcFontSetCreate ();

    if (sort || all)
    {
	FcFontSet	*font_patterns;
	int	j;
	font_patterns = FcFontSort (0, pat, all ? FcFalse : FcTrue, 0, &result);

	if (!font_patterns || font_patterns->nfont == 0)
	{
	    fputs("No fonts installed on the system\n", stderr);
	    return 1;
	}
	for (j = 0; j < font_patterns->nfont; j++)
	{
	    FcPattern  *font_pattern;

	    font_pattern = FcFontRenderPrepare (NULL, pat, font_patterns->fonts[j]);
	    if (font_pattern)
		FcFontSetAdd (fs, font_pattern);
	}

	FcFontSetSortDestroy (font_patterns);
    }
    else
    {
	FcPattern   *match;
	match = FcFontMatch (0, pat, &result);
	if (match)
	    FcFontSetAdd (fs, match);
    }
    FcPatternDestroy (pat);

    if (!format)
    {
	if (os)
	    format = (const FcChar8 *) "%{=unparse}\n";
	else
	    format = (const FcChar8 *) "%{=fcmatch}\n";
    }

    if (fs)
    {
	int	j;

	for (j = 0; j < fs->nfont; j++)
	{
	    FcPattern *font;

	    font = FcPatternFilter (fs->fonts[j], os);

	    if (verbose)
	    {
		FcPatternPrint (font);
	    }
	    else
	    {
	        FcChar8 *s;

		s = FcPatternFormat (font, format);
		if (s)
		{
		    printf ("%s", s);
		    free (s);
		}
	    }

	    FcPatternDestroy (font);
	}
	FcFontSetDestroy (fs);
    }

    if (os)
	FcObjectSetDestroy (os);

    FcFini ();

    return 0;
}
Exemplo n.º 22
0
    bool create(const QString &dir, CFontEngine &fe)
    {
        bool root(Misc::root()), added = false;
        QString fmapDir(Misc::dirSyntax(root ? KFI_ROOT_CFG_DIR : dir));
        CFile old(fmapDir);
        QStringList entries;
        int i;
        FcPattern *pat = FcPatternCreate();
        FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SCALABLE, (void *)0);
        FcFontSet *fs = FcFontList(0, pat, os);

        FcPatternDestroy(pat);
        FcObjectSetDestroy(os);

        for(i = 0; i < fs->nfont; i++)
        {
            QString fName(Misc::fileSyntax(CFcEngine::getFcString(fs->fonts[i], FC_FILE)));
            FcBool scalable = FcFalse;

            if(!fName.isEmpty() && (root || dir.isEmpty() || 0 == fName.find(dir))
               && FcResultMatch == FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &scalable) && scalable)
            {
                const QStringList *existing = old.getEntries(fName);

                if(existing && existing->count())
                    entries += (*existing);
                else
                {
                    int face = 0, numFaces = 0;

                    do
                    {
                        if(fe.openFont(fName, face))
                        {
                            if(fe.hasPsInfo())
                            {
                                if(0 == numFaces)
                                    numFaces = fe.getNumFaces(); // Only really for TTC files...

                                //
                                // Add real
                                addEntry(entries, fe.getPsName(), fName, fmapDir);
                                added = true;

                                //
                                // Add fake entries for X11 generated names
                                switch(fe.getWeight())
                                {
                                    case CFontEngine::WEIGHT_MEDIUM:
                                    case CFontEngine::WEIGHT_REGULAR:
                                    {
                                        QString x11Ps(createX11PsName(fe.getFamilyName()));

                                        if(CFontEngine::ITALIC_ITALIC != fe.getItalic() && CFontEngine::ITALIC_OBLIQUE != fe.getItalic())
                                            addAliasEntry(entries, createName(x11Ps, "Roman", getItalicStr(fe.getItalic())), fe.getPsName());
                                        addAliasEntry(entries, createName(x11Ps, NULL, getItalicStr(fe.getItalic())), fe.getPsName());
                                        break;
                                    }
                                    case CFontEngine::WEIGHT_UNKNOWN:
                                        break;
                                    default:
                                        addAliasEntry(entries, createName(createX11PsName(fe.getFamilyName()), CFontEngine::weightStr(fe.getWeight()),
                                                                          getItalicStr(fe.getItalic())),
                                                      fe.getPsName());
                                }
                            }
                            fe.closeFont();
                        }
                    } while(++face < numFaces);
                }
            }
        }

        bool status = true;

        if(added || entries.count() != old.getLineCount())
        {
            KSaveFile out(fmapDir + FONTMAP);
            QTextStream *stream = out.textStream();

            if(stream)
            {
                QStringList::Iterator it;

                for(it = entries.begin(); it != entries.end(); ++it)
                    *stream << *it << endl;
            }
            else
                status = false;
        }

        //
        // Ensure GS's main Fontmap references our file...
        if(root && status)
        {
            static const char *constGhostscriptDirs[] = {"/usr/share/ghostscript/", "/usr/local/share/ghostscript/", "/usr/share/gs-esp/", NULL};

            QString gsFile = locateFile(FONTMAP, constGhostscriptDirs);

            if(!gsFile.isEmpty())
            {
                const int constMaxLineLen = 1024;
                const char *constRLF = ".runlibfile";

                char line[constMaxLineLen];
                ifstream in(QFile::encodeName(gsFile));

                if(in)
                {
                    QCString fmap(QFile::encodeName(fmapDir + FONTMAP));
                    int lineNum = 0, kfiLine = -1, gsLine = -1, ncLine = -1;

                    do
                    {
                        in.getline(line, constMaxLineLen);

                        if(in.good())
                        {
                            line[constMaxLineLen - 1] = '\0';

                            if(strstr(line, fmap.data()) != NULL && strstr(line, constRLF) != NULL)
                                kfiLine = lineNum;
                            else if(strstr(line, FONTMAP ".GS") != NULL && strstr(line, constRLF) != NULL)
                                gsLine = lineNum;
                            if(-1 == ncLine && '%' != line[0])
                                ncLine = lineNum;
                            lineNum++;
                        }
                    } while(!in.eof() && (-1 == kfiLine || -1 == gsLine));

                    //
                    // If the file doesn't already say to use our Fontmap file, then tell it to!
                    // Also, ensure ours is .runlibfile'd before the main GS one - else problems can occur
                    if(-1 == kfiLine || kfiLine > gsLine)
                    {
                        in.clear();
                        in.seekg(0, ios::end);
                        int size = (streamoff)in.tellg();
                        in.seekg(0, ios::beg);

                        char *buffer = new char[size + strlen(fmap) + strlen(constRLF) + 5];

                        if(buffer)
                        {
                            bool added = false;

                            buffer[0] = '\0';
                            lineNum = 0;

                            do
                            {
                                in.getline(line, constMaxLineLen);

                                if(in.good())
                                {
                                    line[constMaxLineLen - 1] = '\0';

                                    if(lineNum >= ncLine && !added)
                                    {
                                        strcat(buffer, "(");
                                        strcat(buffer, fmap);
                                        strcat(buffer, ") ");
                                        strcat(buffer, constRLF);
                                        strcat(buffer, "\n");
                                        added = true;
                                    }

                                    if(lineNum != kfiLine)
                                    {
                                        strcat(buffer, line);
                                        strcat(buffer, "\n");
                                    }
                                    lineNum++;
                                }
                            } while(!in.eof());

                            in.close();

                            if(added) // Don't re-write GS's Fontmap unless we've actually added something...
                            {
                                KSaveFile out(gsFile);
                                QTextStream *stream = out.textStream();

                                if(stream)
                                    *stream << buffer;
                            }
                            delete[] buffer;
                        }
                    }
                }
            }
        }

        return status;
    }
Exemplo n.º 23
0
static Lisp_Object
xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
  FcResult result;
  Display *display = FRAME_X_DISPLAY (f);
  Lisp_Object val, filename, idx, font_object;
  FcPattern *pat = NULL, *match;
  struct xftfont_info *xftfont_info = NULL;
  struct font *font;
  double size = 0;
  XftFont *xftfont = NULL;
  int spacing;
  int i;
  XGlyphInfo extents;
  FT_Face ft_face;
  FcMatrix *matrix;

  val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
  if (! CONSP (val))
    return Qnil;
  val = XCDR (val);
  filename = XCAR (val);
  idx = XCDR (val);
  size = XINT (AREF (entity, FONT_SIZE_INDEX));
  if (size == 0)
    size = pixel_size;
  pat = FcPatternCreate ();
  FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
  i = FONT_SLANT_NUMERIC (entity) - 100;
  if (i < 0) i = 0;
  FcPatternAddInteger (pat, FC_SLANT, i);
  FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
  FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
  val = AREF (entity, FONT_FAMILY_INDEX);
  if (! NILP (val))
    FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
  val = AREF (entity, FONT_FOUNDRY_INDEX);
  if (! NILP (val))
    FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
  val = AREF (entity, FONT_SPACING_INDEX);
  if (! NILP (val))
    FcPatternAddInteger (pat, FC_SPACING, XINT (val));
  val = AREF (entity, FONT_DPI_INDEX);
  if (! NILP (val))
    {
      double dbl = XINT (val);

      FcPatternAddDouble (pat, FC_DPI, dbl);
    }
  val = AREF (entity, FONT_AVGWIDTH_INDEX);
  if (INTEGERP (val) && XINT (val) == 0)
    FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
  /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
     over 10x20-ISO8859-1.pcf.gz).  */
  FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));

  xftfont_add_rendering_parameters (pat, entity);

  FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
  FcPatternAddInteger (pat, FC_INDEX, XINT (idx));


  block_input ();

  /* Substitute in values from X resources and XftDefaultSet.  */
  XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
  match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
  xftfont_fix_match (pat, match);

  FcPatternDestroy (pat);
  xftfont = XftFontOpenPattern (display, match);
  if (!xftfont)
    {
      unblock_input ();
      XftPatternDestroy (match);
      return Qnil;
    }
  ft_face = XftLockFace (xftfont);
  unblock_input ();

  /* We should not destroy PAT here because it is kept in XFTFONT and
     destroyed automatically when XFTFONT is closed.  */
  font_object = font_build_object (VECSIZE (struct xftfont_info),
				   Qxft, entity, size);
  ASET (font_object, FONT_FILE_INDEX, filename);
  font = XFONT_OBJECT (font_object);
  font->pixel_size = size;
  font->driver = &xftfont_driver;
  font->encoding_charset = font->repertory_charset = -1;

  xftfont_info = (struct xftfont_info *) font;
  xftfont_info->display = display;
  xftfont_info->xftfont = xftfont;
  xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
  /* This means that there's no need of transformation.  */
  xftfont_info->matrix.xx = 0;
  if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
      == FcResultMatch)
    {
      xftfont_info->matrix.xx = 0x10000L * matrix->xx;
      xftfont_info->matrix.yy = 0x10000L * matrix->yy;
      xftfont_info->matrix.xy = 0x10000L * matrix->xy;
      xftfont_info->matrix.yx = 0x10000L * matrix->yx;
    }
  if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
  else
    spacing = FC_PROPORTIONAL;
  if (! ascii_printable[0])
    {
      int ch;
      for (ch = 0; ch < 95; ch++)
	ascii_printable[ch] = ' ' + ch;
    }
  block_input ();

  /* Unfortunately Xft doesn't provide a way to get minimum char
     width.  So, we set min_width to space_width.  */

  if (spacing != FC_PROPORTIONAL
#ifdef FC_DUAL
      && spacing != FC_DUAL
#endif	/* FC_DUAL */
      )
    {
      font->min_width = font->max_width = font->average_width
	= font->space_width = xftfont->max_advance_width;
      XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
    }
  else
    {
      XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
      font->min_width = font->max_width = font->space_width
	= extents.xOff;
      if (font->space_width <= 0)
	/* dirty workaround */
	font->space_width = pixel_size;
      XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
      font->average_width = (font->space_width + extents.xOff) / 95;
    }
  unblock_input ();

  font->ascent = xftfont->ascent;
  font->descent = xftfont->descent;
  if (pixel_size >= 5)
    {
      /* The above condition is a dirty workaround because
	 XftTextExtents8 behaves strangely for some fonts
	 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
      if (font->ascent < extents.y)
	font->ascent = extents.y;
      if (font->descent < extents.height - extents.y)
	font->descent = extents.height - extents.y;
    }
  font->height = font->ascent + font->descent;

  if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
    {
      int upEM = ft_face->units_per_EM;

      font->underline_position = -ft_face->underline_position * size / upEM;
      font->underline_thickness = ft_face->underline_thickness * size / upEM;
      if (font->underline_thickness > 2)
	font->underline_position -= font->underline_thickness / 2;
    }
  else
    {
      font->underline_position = -1;
      font->underline_thickness = 0;
    }
#ifdef HAVE_LIBOTF
  xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
  xftfont_info->otf = NULL;
#endif	/* HAVE_LIBOTF */
  xftfont_info->ft_size = ft_face->size;

  font->baseline_offset = 0;
  font->relative_compose = 0;
  font->default_ascent = 0;
  font->vertical_centering = false;
#ifdef FT_BDF_H
  if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
    {
      BDF_PropertyRec rec;

      if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->baseline_offset = rec.u.integer;
      if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->relative_compose = rec.u.integer;
      if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->default_ascent = rec.u.integer;
    }
#endif

  return font_object;
}
Exemplo n.º 24
0
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr)
{
    if (!usrPtr)
        return 0;
    QFontDef fontDef = f;

    QFontEngineFT *engine;
    FontFile *fontfile = static_cast<FontFile *> (usrPtr);
    QFontEngine::FaceId fid;
    fid.filename = fontfile->fileName.toLocal8Bit();
    fid.index = fontfile->indexValue;

    bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
    engine = new QFontEngineFT(fontDef);

    QFontEngineFT::GlyphFormat format;
    // try and get the pattern
    FcPattern *pattern = FcPatternCreate();

    FcValue value;
    value.type = FcTypeString;
        QByteArray cs = fontDef.family.toUtf8();
    value.u.s = (const FcChar8 *)cs.data();
    FcPatternAdd(pattern,FC_FAMILY,value,true);

    value.u.s = (const FcChar8 *)fid.filename.data();
    FcPatternAdd(pattern,FC_FILE,value,true);

    value.type = FcTypeInteger;
    value.u.i = fid.index;
    FcPatternAdd(pattern,FC_INDEX,value,true);

    FcResult result;
    FcPattern *match = FcFontMatch(0, pattern, &result);
    if (match) {
        QFontEngineFT::HintStyle default_hint_style;
        if (f.hintingPreference != QFont::PreferDefaultHinting) {
            switch (f.hintingPreference) {
            case QFont::PreferNoHinting:
                default_hint_style = QFontEngineFT::HintNone;
                break;
            case QFont::PreferVerticalHinting:
                default_hint_style = QFontEngineFT::HintLight;
                break;
            case QFont::PreferFullHinting:
            default:
                default_hint_style = QFontEngineFT::HintFull;
                break;
            }
        } else {
            int hint_style = 0;
            if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch)
                hint_style = QFontEngineFT::HintFull;
            switch (hint_style) {
            case FC_HINT_NONE:
                default_hint_style = QFontEngineFT::HintNone;
                break;
            case FC_HINT_SLIGHT:
                default_hint_style = QFontEngineFT::HintLight;
                break;
            case FC_HINT_MEDIUM:
                default_hint_style = QFontEngineFT::HintMedium;
                break;
            default:
                default_hint_style = QFontEngineFT::HintFull;
                break;
            }
        }
        engine->setDefaultHintStyle(default_hint_style);

        if (antialias) {
            QFontEngineFT::SubpixelAntialiasingType subpixelType = QFontEngineFT::Subpixel_None;
            int subpixel = FC_RGBA_NONE;

            FcPatternGetInteger(match, FC_RGBA, 0, &subpixel);
            if (subpixel == FC_RGBA_UNKNOWN)
                subpixel = FC_RGBA_NONE;

            switch (subpixel) {
                case FC_RGBA_NONE: subpixelType = QFontEngineFT::Subpixel_None; break;
                case FC_RGBA_RGB: subpixelType = QFontEngineFT::Subpixel_RGB; break;
                case FC_RGBA_BGR: subpixelType = QFontEngineFT::Subpixel_BGR; break;
                case FC_RGBA_VRGB: subpixelType = QFontEngineFT::Subpixel_VRGB; break;
                case FC_RGBA_VBGR: subpixelType = QFontEngineFT::Subpixel_VBGR; break;
                default: break;
            }

            format = subpixelType == QFontEngineFT::Subpixel_None
                        ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32;
            engine->subpixelType = subpixelType;
        } else
            format = QFontEngineFT::Format_Mono;

        FcPatternDestroy(match);
    } else
        format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;

    FcPatternDestroy(pattern);

    if (!engine->init(fid,antialias,format)) {
        delete engine;
        engine = 0;
        return engine;
    }
    if (engine->invalid()) {
        delete engine;
        engine = 0;
    } else if (scriptRequiresOpenType(script)) {
        HB_Face hbFace = engine->initializedHarfbuzzFace();
        if (!hbFace || !hbFace->supported_scripts[script]) {
            delete engine;
            engine = 0;
        }
    }

    return engine;
}
Exemplo n.º 25
0
/**
 * grx_font_load_full:
 * @family: (nullable): the font family name or %NULL
 * @size: the preferred size in points or -1 for any size
 * @dpi: the screen resolution or -1 to ignore dpi
 * @weight: the font weight (e.g. bold) or -1 for any weight
 * @slant: the font slant (e.g. italic) or -1 for any slant
 * @width: the font width (e.g. narrow) or -1 for any width
 * @monospace: set to %TRUE to prefer a monospace font
 * @lang: (nullable): a RFC-3066-style language code or %NULL
 * @script: (nullable): an ISO 15924 script code or %NULL
 * @err: pointer to hold an error
 *
 * Loads the font that best matches the parameters.
 *
 * Uses fontconfig for font matching.
 *
 * Returns: (transfer full) (nullable): the font or %NULL if there was an error
 */
GrxFont *grx_font_load_full(const gchar *family, gint size, gint dpi,
                            GrxFontWeight weight, GrxFontSlant slant,
                            GrxFontWidth width, gboolean monospace,
                            const gchar *lang, const gchar *script, GError **err)
{
    FcPattern *pattern, *match;
    FcResult result;
    GrxFont *font;
    FcChar8 *file;

    if (!FcInit()) {
        g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR,
            "Failed to init fontconfig");
        return NULL;
    }

    pattern = FcPatternCreate();
    FcPatternAddBool(pattern, FC_SCALABLE, FcFalse);
    FcPatternAddBool(pattern, FC_OUTLINE, FcFalse);
    FcPatternAddString(pattern, FC_FONTFORMAT, (FcChar8 *)"PCF");
    if (family) {
        FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *)family);
    }
    if (size >= 0) {
        FcPatternAddDouble(pattern, FC_SIZE, size);
    }
    if (dpi >= 0) {
        FcPatternAddDouble(pattern, FC_DPI, dpi);
    }
    switch (weight) {
    case GRX_FONT_WEIGHT_REGULAR:
        FcPatternAddInteger(pattern, FC_WEIGHT, 80);
        break;
    case GRX_FONT_WEIGHT_BOLD:
        FcPatternAddInteger(pattern, FC_WEIGHT, 200);
        break;
    }
    switch (slant) {
    case GRX_FONT_SLANT_REGULAR:
        FcPatternAddInteger(pattern, FC_SLANT, 0);
        break;
    case GRX_FONT_SLANT_ITALIC:
        FcPatternAddInteger(pattern, FC_SLANT, 100);
        break;
    }
    switch (width) {
    case GRX_FONT_WIDTH_NARROW:
        FcPatternAddInteger(pattern, FC_WIDTH, 75);
        break;
    case GRX_FONT_WIDTH_REGULAR:
        FcPatternAddInteger(pattern, FC_WIDTH, 100);
        break;
    case GRX_FONT_WIDTH_WIDE:
        FcPatternAddInteger(pattern, FC_WIDTH, 125);
        break;
    }
    if (monospace) {
        FcPatternAddInteger(pattern, FC_SPACING, 100);
    }
    if (lang) {
        FcPatternAddString(pattern, FC_LANG, (FcChar8 *)lang);
    }
    if (script) {
        FcPatternAddCharSet(pattern, FC_CHARSET, script_to_charset(script));
    }
    {
        FcChar8 *pattern_str;

        pattern_str = FcNameUnparse(pattern);
        g_debug("searching for pattern: %s", pattern_str);
        free(pattern_str);
    }

    FcConfigSubstitute(NULL, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);
    match = FcFontMatch(NULL, pattern, &result);

    if (!match) {
        // TODO: use result for better error
        g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR,
            "Failed to find match");
        FcPatternDestroy(pattern);
        return NULL;
    }

    if (FcPatternGetString(match, FC_FILE, 0, &file) != FcResultMatch) {
        g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR,
            "Failed to get file name");
        FcPatternDestroy(match);
        FcPatternDestroy(pattern);
        return NULL;
    }

    font = grx_font_load_from_file((gchar *)file, err);

    FcPatternDestroy(match);
    FcPatternDestroy(pattern);

    return font;
}
bool FontConfigDirect::Match(std::string* result_family,
                             unsigned* result_filefaceid,
                             bool filefaceid_valid, unsigned filefaceid,
                             const std::string& family,
                             const void* data, size_t characters_bytes,
                             bool* is_bold, bool* is_italic) {
    if (family.length() > kMaxFontFamilyLength)
        return false;

    SkAutoMutexAcquire ac(mutex_);

    // Given |family|, |is_bold| and |is_italic| but not |data|, the result will
    // be a function of these three parameters, and thus eligible for caching.
    // This is the fast path for |SkTypeface::CreateFromName()|.
    bool eligible_for_cache = !family.empty() && is_bold && is_italic && !data;
    if (eligible_for_cache) {
        int style = (*is_bold ? SkTypeface::kBold : 0 ) |
                    (*is_italic ? SkTypeface::kItalic : 0);
        FontMatchKey key = FontMatchKey(family, style);
        const std::map<FontMatchKey, FontMatch>::const_iterator i =
            font_match_cache_.find(key);
        if (i != font_match_cache_.end()) {
            *is_bold = i->second.is_bold;
            *is_italic = i->second.is_italic;
            if (result_family)
                *result_family = i->second.family;
            if (result_filefaceid)
                *result_filefaceid = i->second.filefaceid;
            return true;
        }
    }

    FcPattern* pattern = FcPatternCreate();

    if (filefaceid_valid) {
        const std::map<unsigned, std::string>::const_iterator
            i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid));
        if (i == fileid_to_filename_.end()) {
            FcPatternDestroy(pattern);
            return false;
        }
        int face_index = filefaceid & 0xfu;
        FcPatternAddString(pattern, FC_FILE,
            reinterpret_cast<const FcChar8*>(i->second.c_str()));
        // face_index is added only when family is empty because it is not
        // necessary to uniquiely identify a font if both file and
        // family are given.
        if (family.empty())
            FcPatternAddInteger(pattern, FC_INDEX, face_index);
    }
    if (!family.empty()) {
        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*) family.c_str());
    }

    FcCharSet* charset = NULL;
    if (data) {
        charset = FcCharSetCreate();
        const uint16_t* chars = (const uint16_t*) data;
        size_t num_chars = characters_bytes / 2;
        for (size_t i = 0; i < num_chars; ++i) {
            if (U16_IS_SURROGATE(chars[i])
                && U16_IS_SURROGATE_LEAD(chars[i])
                && i != num_chars - 1
                && U16_IS_TRAIL(chars[i + 1])) {
                FcCharSetAddChar(charset, U16_GET_SUPPLEMENTARY(chars[i], chars[i+1]));
                i++;
            } else {
                FcCharSetAddChar(charset, chars[i]);
            }
        }
        FcPatternAddCharSet(pattern, FC_CHARSET, charset);
        FcCharSetDestroy(charset);  // pattern now owns it.
    }

    FcPatternAddInteger(pattern, FC_WEIGHT,
                        is_bold && *is_bold ? FC_WEIGHT_BOLD
                                            : FC_WEIGHT_NORMAL);
    FcPatternAddInteger(pattern, FC_SLANT,
                        is_italic && *is_italic ? FC_SLANT_ITALIC
                                                : FC_SLANT_ROMAN);
    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);

    FcConfigSubstitute(NULL, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    // Font matching:
    // CSS often specifies a fallback list of families:
    //    font-family: a, b, c, serif;
    // However, fontconfig will always do its best to find *a* font when asked
    // for something so we need a way to tell if the match which it has found is
    // "good enough" for us. Otherwise, we can return NULL which gets piped up
    // and lets WebKit know to try the next CSS family name. However, fontconfig
    // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
    // wish to support that.
    //
    // Thus, if a specific family is requested we set @family_requested. Then we
    // record two strings: the family name after config processing and the
    // family name after resolving. If the two are equal, it's a good match.
    //
    // So consider the case where a user has mapped Arial to Helvetica in their
    // config.
    //    requested family: "Arial"
    //    post_config_family: "Helvetica"
    //    post_match_family: "Helvetica"
    //      -> good match
    //
    // and for a missing font:
    //    requested family: "Monaco"
    //    post_config_family: "Monaco"
    //    post_match_family: "Times New Roman"
    //      -> BAD match
    //
    // However, we special-case fallback fonts; see IsFallbackFontAllowed().
    FcChar8* post_config_family;
    FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family);

    FcResult result;
    FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
    if (!font_set) {
        FcPatternDestroy(pattern);
        return false;
    }

    FcPattern* match = MatchFont(font_set, post_config_family, family);
    if (!match) {
        FcPatternDestroy(pattern);
        FcFontSetDestroy(font_set);
        return false;
    }

    FcPatternDestroy(pattern);

    FcChar8* c_filename;
    if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }
    int face_index;
    if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }

    FontMatch font_match;
    if (filefaceid_valid) {
        font_match.filefaceid = filefaceid;
    } else {
        unsigned out_fileid;
        const std::string filename(reinterpret_cast<char*>(c_filename));
        const std::map<std::string, unsigned>::const_iterator
            i = filename_to_fileid_.find(filename);
        if (i == filename_to_fileid_.end()) {
            out_fileid = next_file_id_++;
            filename_to_fileid_[filename] = out_fileid;
            fileid_to_filename_[out_fileid] = filename;
        } else {
            out_fileid = i->second;
        }
        // fileid stored in filename_to_fileid_ and fileid_to_filename_ is
        // unique only up to the font file. We have to encode face_index for
        // the out param.
        font_match.filefaceid =
            FileIdAndFaceIndexToFileFaceId(out_fileid, face_index);
    }

    bool success = GetFontProperties(match,
                                     &font_match.family,
                                     &font_match.is_bold,
                                     &font_match.is_italic);
    FcFontSetDestroy(font_set);

    if (success) {
        // If eligible, cache the result of the matching.
        if (eligible_for_cache) {
            int style = (*is_bold ? SkTypeface::kBold : 0 ) |
                        (*is_italic ? SkTypeface::kItalic : 0);
            font_match_cache_[FontMatchKey(family, style)] = font_match;
        }

        if (result_family)
            *result_family = font_match.family;
        if (result_filefaceid)
            *result_filefaceid = font_match.filefaceid;
        if (is_bold)
            *is_bold = font_match.is_bold;
        if (is_italic)
            *is_italic = font_match.is_italic;
    }

    return success;
}
Exemplo n.º 27
0
QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
    QStringList fallbackFamilies;
    FcPattern *pattern = FcPatternCreate();
    if (!pattern)
        return fallbackFamilies;

    FcValue value;
    value.type = FcTypeString;
    QByteArray cs = family.toUtf8();
    value.u.s = (const FcChar8 *)cs.data();
    FcPatternAdd(pattern,FC_FAMILY,value,true);

    int slant_value = FC_SLANT_ROMAN;
    if (style == QFont::StyleItalic)
        slant_value = FC_SLANT_ITALIC;
    else if (style == QFont::StyleOblique)
        slant_value = FC_SLANT_OBLIQUE;
    FcPatternAddInteger(pattern, FC_SLANT, slant_value);

    Q_ASSERT(uint(script) < QChar::ScriptCount);
    if (*specialLanguages[script] != '\0') {
        FcLangSet *ls = FcLangSetCreate();
        FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
        FcPatternAddLangSet(pattern, FC_LANG, ls);
        FcLangSetDestroy(ls);
    } else if (!family.isEmpty()) {
        // If script is Common or Han, then it may include languages like CJK,
        // we should attach system default language set to the pattern
        // to obtain correct font fallback list (i.e. if LANG=zh_CN
        // then we normally want to use a Chinese font for CJK text;
        // while a Japanese font should be used for that if LANG=ja)
        FcPattern *dummy = FcPatternCreate();
        FcDefaultSubstitute(dummy);
        FcChar8 *lang = 0;
        FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
        if (res == FcResultMatch)
            FcPatternAddString(pattern, FC_LANG, lang);
        FcPatternDestroy(dummy);
    }

    const char *stylehint = getFcFamilyForStyleHint(styleHint);
    if (stylehint) {
        value.u.s = (const FcChar8 *)stylehint;
        FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
    }

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult result = FcResultMatch;
    FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result);
    FcPatternDestroy(pattern);

    if (fontSet) {
        for (int i = 0; i < fontSet->nfont; i++) {
            FcChar8 *value = 0;
            if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
                continue;
            //         capitalize(value);
            QString familyName = QString::fromUtf8((const char *)value);
            if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) &&
                familyName.compare(family, Qt::CaseInsensitive)) {
                fallbackFamilies << familyName;
            }
        }
        FcFontSetDestroy(fontSet);
    }
//    qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies;

    return fallbackFamilies;
}
Exemplo n.º 28
0
void WebFontInfo::fallbackFontForChar(WebUChar32 c, const char* preferredLocale, WebFallbackFont* fallbackFont)
{
    FcCharSet* cset = FcCharSetCreate();
    FcCharSetAddChar(cset, c);
    FcPattern* pattern = FcPatternCreate();

    FcValue fcvalue;
    fcvalue.type = FcTypeCharSet;
    fcvalue.u.c = cset;
    FcPatternAdd(pattern, FC_CHARSET, fcvalue, FcFalse);

    fcvalue.type = FcTypeBool;
    fcvalue.u.b = FcTrue;
    FcPatternAdd(pattern, FC_SCALABLE, fcvalue, FcFalse);

    if (preferredLocale) {
        FcLangSet* langset = FcLangSetCreate();
        FcLangSetAdd(langset, reinterpret_cast<const FcChar8 *>(preferredLocale));
        FcPatternAddLangSet(pattern, FC_LANG, langset);
        FcLangSetDestroy(langset);
    }

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult result;
    FcFontSet* fontSet = FcFontSort(0, pattern, 0, 0, &result);
    FcPatternDestroy(pattern);
    FcCharSetDestroy(cset);

    if (!fontSet) {
        fallbackFont->name = WebCString();
        fallbackFont->isBold = false;
        fallbackFont->isItalic = false;
        return;
    }
    // Older versions of fontconfig have a bug where they cannot select
    // only scalable fonts so we have to manually filter the results.
    for (int i = 0; i < fontSet->nfont; ++i) {
        FcPattern* current = fontSet->fonts[i];
        FcBool isScalable;

        if (FcPatternGetBool(current, FC_SCALABLE, 0, &isScalable) != FcResultMatch
            || !isScalable)
            continue;

        // fontconfig can also return fonts which are unreadable
        FcChar8* cFilename;
        if (FcPatternGetString(current, FC_FILE, 0, &cFilename) != FcResultMatch)
            continue;

        if (access(reinterpret_cast<char*>(cFilename), R_OK))
            continue;

        const char* fontFilename = reinterpret_cast<char*>(cFilename);
        fallbackFont->filename = WebCString(fontFilename, strlen(fontFilename));

        // Index into font collection.
        int ttcIndex;
        if (FcPatternGetInteger(current, FC_INDEX, 0, &ttcIndex) != FcResultMatch && ttcIndex < 0)
            continue;
        fallbackFont->ttcIndex = ttcIndex;

        FcChar8* familyName;
        if (FcPatternGetString(current, FC_FAMILY, 0, &familyName) == FcResultMatch) {
            const char* charFamily = reinterpret_cast<char*>(familyName);
            fallbackFont->name = WebCString(charFamily, strlen(charFamily));
        }
        int weight;
        if (FcPatternGetInteger(current, FC_WEIGHT, 0, &weight) == FcResultMatch)
            fallbackFont->isBold = weight >= FC_WEIGHT_BOLD;
        else
            fallbackFont->isBold = false;
        int slant;
        if (FcPatternGetInteger(current, FC_SLANT, 0, &slant) == FcResultMatch)
            fallbackFont->isItalic = slant != FC_SLANT_ROMAN;
        else
            fallbackFont->isItalic = false;
        FcFontSetDestroy(fontSet);
        return;
    }

    FcFontSetDestroy(fontSet);
}
Exemplo n.º 29
0
MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_cache,
  ExceptionInfo *exception)
{
#if !defined(FC_FULLNAME)
#define FC_FULLNAME "fullname"
#endif

  char
    extension[MagickPathExtent],
    name[MagickPathExtent];

  FcChar8
    *family,
    *file,
    *fullname,
    *style;

  FcConfig
    *font_config;

  FcFontSet
    *font_set;

  FcObjectSet
    *object_set;

  FcPattern
    *pattern;

  FcResult
    status;

  int
    slant,
    width,
    weight;

  register ssize_t
    i;

  TypeInfo
    *type_info;

  /*
    Load system fonts.
  */
  (void) exception;
  font_config=FcInitLoadConfigAndFonts();
  if (font_config == (FcConfig *) NULL)
    return(MagickFalse);
  font_set=(FcFontSet *) NULL;
  object_set=FcObjectSetBuild(FC_FULLNAME,FC_FAMILY,FC_STYLE,FC_SLANT,
    FC_WIDTH,FC_WEIGHT,FC_FILE,(char *) NULL);
  if (object_set != (FcObjectSet *) NULL)
    {
      pattern=FcPatternCreate();
      if (pattern != (FcPattern *) NULL)
        {
          font_set=FcFontList(0,pattern,object_set);
          FcPatternDestroy(pattern);
        }
      FcObjectSetDestroy(object_set);
    }
  if (font_set == (FcFontSet *) NULL)
    {
      FcConfigDestroy(font_config);
      return(MagickFalse);
    }
  for (i=0; i < (ssize_t) font_set->nfont; i++)
  {
    status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
    if (status != FcResultMatch)
      continue;
    status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
    if (status != FcResultMatch)
      continue;
    *extension='\0';
    GetPathComponent((const char *) file,ExtensionPath,extension);
    if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
      continue;
    type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
    if (type_info == (TypeInfo *) NULL)
      continue;
    (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
    type_info->path=ConstantString("System Fonts");
    type_info->signature=MagickCoreSignature;
    (void) CopyMagickString(name,"Unknown",MagickPathExtent);
    status=FcPatternGetString(font_set->fonts[i],FC_FULLNAME,0,&fullname);
    if ((status == FcResultMatch) && (fullname != (FcChar8 *) NULL))
      (void) CopyMagickString(name,(const char *) fullname,MagickPathExtent);
    else
      {
        if (family != (FcChar8 *) NULL)
          (void) CopyMagickString(name,(const char *) family,MagickPathExtent);
        status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
        if ((status == FcResultMatch) && (style != (FcChar8 *) NULL) &&
            (LocaleCompare((const char *) style,"Regular") != 0))
          {
            (void) ConcatenateMagickString(name," ",MagickPathExtent);
            (void) ConcatenateMagickString(name,(const char *) style,
              MagickPathExtent);
          }
      }
    type_info->name=ConstantString(name);
    (void) SubstituteString(&type_info->name," ","-");
    type_info->family=ConstantString((const char *) family);
    status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
    type_info->style=NormalStyle;
    if (slant == FC_SLANT_ITALIC)
      type_info->style=ItalicStyle;
    if (slant == FC_SLANT_OBLIQUE)
      type_info->style=ObliqueStyle;
    status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
    type_info->stretch=NormalStretch;
    if (width >= FC_WIDTH_ULTRACONDENSED)
      type_info->stretch=UltraCondensedStretch;
    if (width >= FC_WIDTH_EXTRACONDENSED)
      type_info->stretch=ExtraCondensedStretch;
    if (width >= FC_WIDTH_CONDENSED)
      type_info->stretch=CondensedStretch;
    if (width >= FC_WIDTH_SEMICONDENSED)
      type_info->stretch=SemiCondensedStretch;
    if (width >= FC_WIDTH_NORMAL)
      type_info->stretch=NormalStretch;
    if (width >= FC_WIDTH_SEMIEXPANDED)
      type_info->stretch=SemiExpandedStretch;
    if (width >= FC_WIDTH_EXPANDED)
      type_info->stretch=ExpandedStretch;
    if (width >= FC_WIDTH_EXTRAEXPANDED)
      type_info->stretch=ExtraExpandedStretch;
    if (width >= FC_WIDTH_ULTRAEXPANDED)
      type_info->stretch=UltraExpandedStretch;
    type_info->weight=400;
    status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
    if (weight >= FC_WEIGHT_THIN)
      type_info->weight=100;
    if (weight >= FC_WEIGHT_EXTRALIGHT)
      type_info->weight=200;
    if (weight >= FC_WEIGHT_LIGHT)
      type_info->weight=300;
    if (weight >= FC_WEIGHT_NORMAL)
      type_info->weight=400;
    if (weight >= FC_WEIGHT_MEDIUM)
      type_info->weight=500;
    if (weight >= FC_WEIGHT_DEMIBOLD)
      type_info->weight=600;
    if (weight >= FC_WEIGHT_BOLD)
      type_info->weight=700;
    if (weight >= FC_WEIGHT_EXTRABOLD)
      type_info->weight=800;
    if (weight >= FC_WEIGHT_BLACK)
      type_info->weight=900;
    type_info->glyphs=ConstantString((const char *) file);
    (void) AddValueToSplayTree(type_cache,type_info->name,type_info);
  }
  FcFontSetDestroy(font_set);
  FcConfigDestroy(font_config);
  return(MagickTrue);
}
Exemplo n.º 30
0
QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
{
    QStringList fallbackFamilies;
    FcPattern *pattern = FcPatternCreate();
    if (!pattern)
        return fallbackFamilies;

    FcValue value;
    value.type = FcTypeString;
    QByteArray cs = family.toUtf8();
    value.u.s = (const FcChar8 *)cs.data();
    FcPatternAdd(pattern,FC_FAMILY,value,true);

    int slant_value = FC_SLANT_ROMAN;
    if (style == QFont::StyleItalic)
        slant_value = FC_SLANT_ITALIC;
    else if (style == QFont::StyleOblique)
        slant_value = FC_SLANT_OBLIQUE;
    FcPatternAddInteger(pattern, FC_SLANT, slant_value);

    if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') {
        Q_ASSERT(script < QUnicodeTables::ScriptCount);
        FcLangSet *ls = FcLangSetCreate();
        FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
        FcPatternAddLangSet(pattern, FC_LANG, ls);
        FcLangSetDestroy(ls);
    }

    const char *stylehint = getFcFamilyForStyleHint(styleHint);
    if (stylehint) {
        value.u.s = (const FcChar8 *)stylehint;
        FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
    }

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult result = FcResultMatch;
    FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result);
    FcPatternDestroy(pattern);

    if (fontSet) {
        if (result == FcResultMatch) {
            for (int i = 0; i < fontSet->nfont; i++) {
                FcChar8 *value = 0;
                if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
                    continue;
                //         capitalize(value);
                QString familyName = QString::fromUtf8((const char *)value);
                if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) &&
                    familyName.compare(family, Qt::CaseInsensitive)) {
                    fallbackFamilies << familyName;
                }
            }
        }
        FcFontSetDestroy(fontSet);
    }
//    qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies;

    return fallbackFamilies;
}