Esempio n. 1
0
 void property(string&& property, int* dst) const {
   FcPatternGetInteger(m_pattern, property.c_str(), 0, dst);
 }
static void populateFromPattern(FcPattern *pattern)
{
    QString familyName;
    FcChar8 *value = 0;
    int weight_value;
    int slant_value;
    int spacing_value;
    int width_value;
    FcChar8 *file_value;
    int indexValue;
    FcChar8 *foundry_value;
    FcChar8 *style_value;
    FcBool scalable;
    FcBool antialias;

    if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
        return;

    familyName = QString::fromUtf8((const char *)value);
    if (familyName == QLatin1String("Open Sans")) {
        FcChar8 *styl = 0;
        if (FcPatternGetString(pattern, FC_STYLE, 0, &styl) == FcResultMatch) {
            QString style = QString::fromUtf8(reinterpret_cast<const char *>(styl));
            if (style == QLatin1String("Semibold")) {
                familyName.append(QChar(QChar::Space)).append(style);
            }
        }
    }

    slant_value = FC_SLANT_ROMAN;
    weight_value = FC_WEIGHT_REGULAR;
    spacing_value = FC_PROPORTIONAL;
    file_value = 0;
    indexValue = 0;
    scalable = FcTrue;


    if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
        slant_value = FC_SLANT_ROMAN;
    if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
        weight_value = FC_WEIGHT_REGULAR;
    if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
        width_value = FC_WIDTH_NORMAL;
    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
        spacing_value = FC_PROPORTIONAL;
    if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
        file_value = 0;
    if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
        indexValue = 0;
    if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
        scalable = FcTrue;
    if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
        foundry_value = 0;
    if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
        style_value = 0;
    if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
        antialias = true;

    QSupportedWritingSystems writingSystems;
    FcLangSet *langset = 0;
    FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
    if (res == FcResultMatch) {
        bool hasLang = false;
        for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
            const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
            if (lang) {
                FcLangResult langRes = FcLangSetHasLang(langset, lang);
                if (langRes != FcLangDifferentLang) {
                    writingSystems.setSupported(QFontDatabase::WritingSystem(j));
                    hasLang = true;
                }
            }
        }
        if (!hasLang)
            // none of our known languages, add it to the other set
            writingSystems.setSupported(QFontDatabase::Other);
    } 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);
    }

#if FC_VERSION >= 20297
    for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
        if (writingSystems.supported(QFontDatabase::WritingSystem(j))
            && requiresOpenType(j) && openType[j]) {
            FcChar8 *cap;
            res = FcPatternGetString (pattern, 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 = QString::fromLocal8Bit((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);
    // Note: weight should really be an int but registerFont incorrectly uses an enum
    QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));

    double pixel_size = 0;
    if (!scalable)
        FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);

    bool fixedPitch = spacing_value >= FC_MONO;
    // Note: stretch should really be an int but registerFont incorrectly uses an enum
    QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
    QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
    QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
//        qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;

    for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k)
        QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value));

}
Esempio n. 3
0
    void find_font(font & f, std::string const& name, int height, int weight, int style)
    {
        // FIXME: shouldn't require fonts to be empty
        BOOST_ASSERT(!f);

        FcValue fcval;

        // build pattern
        FcPattern * pattern = FcPatternCreate();

        // typeface name
        fcval.type = FcTypeString;
        fcval.u.s = (FcChar8 const*) name.c_str();
        FcPatternAdd(pattern, FC_FAMILY, fcval, FcTrue);

        // pixel size
        fcval.type = FcTypeInteger;
        fcval.u.i = height;
        FcPatternAdd(pattern, FC_PIXEL_SIZE, fcval, FcTrue);

        // italic
        if (style & font_style::italic)
        {
            fcval.type = FcTypeInteger;
            fcval.u.i = FC_SLANT_ITALIC;
            FcPatternAdd(pattern, FC_SLANT, fcval, FcTrue);
        }

        // weight
        fcval.type = FcTypeInteger;
        switch (weight)
        {
        case font_weight::thin:          fcval.u.i = FC_WEIGHT_THIN; break;
        case font_weight::extra_light:   fcval.u.i = FC_WEIGHT_EXTRALIGHT; break;
        case font_weight::light:         fcval.u.i = FC_WEIGHT_LIGHT; break;
        case font_weight::normal:        fcval.u.i = FC_WEIGHT_NORMAL; break;
        case font_weight::medium:        fcval.u.i = FC_WEIGHT_MEDIUM; break;
        case font_weight::semi_bold:     fcval.u.i = FC_WEIGHT_SEMIBOLD; break;
        case font_weight::bold:          fcval.u.i = FC_WEIGHT_BOLD; break;
        case font_weight::ultra_bold:    fcval.u.i = FC_WEIGHT_ULTRABOLD; break;
        case font_weight::heavy:         fcval.u.i = FC_WEIGHT_HEAVY; break;
        default:                         fcval.u.i = FC_WEIGHT_NORMAL; break;
        };
        FcPatternAdd(pattern, FC_WEIGHT, fcval, FcTrue);

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

        FcResult res;
        FcPattern * real_pattern = FcFontMatch(NULL, pattern, &res);

        FcPatternDestroy(pattern);

        // get filename
        if (real_pattern)
        {
            char * fname;
            int id;

            FcPatternGetString(real_pattern, FC_FILE, 0, (FcChar8 **) &fname);
            FcPatternGetInteger(real_pattern, FC_INDEX, 0, &id);

            // load font
            FT_Face face;
            if (FT_New_Face(::ftlib, fname, id, &face))
                return;

            FcPatternDestroy(real_pattern);

            // create font
            ft_font_extra * extra = static_cast<ft_font_extra *>(f.extra_data);

            extra->face = face;

            FT_Set_Pixel_Sizes(face, 0, height);

            // get avg char width/height
            point pt = detail::font_units_to_pixels(face, face->max_advance_width, face->max_advance_height);
            extra->width = pt.x;
            extra->height = pt.y;

            pt = detail::font_units_to_pixels(face, 0, face->ascender);
            extra->ascender = pt.y;

            pt = detail::font_units_to_pixels(face, 0, face->descender);
            extra->descender = pt.y;
        }
    }
int PsychRebuildFont(void)
{
	// Destroy old font object, if any:
	if (faceT || faceM) {
		// Delete OGLFT face object:
		if (faceT) delete(faceT);
		faceT = NULL;
		
		if (faceM) delete(faceM);
		faceM = NULL;

		if (_verbosity > 3) fprintf(stderr, "libptbdrawtext_ftgl: Destroying old font face...\n");
		
		// Delete underlying FreeType representation:
		FT_Done_Face(ft_face);
		ft_face = NULL;
	}

	if (_useOwnFontmapper) {
		FcResult result;
		FcPattern* target = NULL;
		
		if (_fontName[0] == '-') {
			// _fontName starts with a '-' dash: This is not a simple font family string but a special
			// fontspec string in FontConfig's special format. It contains many possible required font
			// properties encoded in the string. Parse it into a font matching pattern:
			target = FcNameParse((FcChar8*) &(_fontName[1]));
			
			// Need to manually add the current _fontSize, otherwise inconsistent stuff may happen:
			FcPatternAddDouble(target, FC_PIXEL_SIZE, _fontSize);
		}
		else {
			// _fontName contains only font family name: Build matching pattern based on _fontSize and
			// the flags provided in _fontStyle, according to the conventions in Psychtoolbox Screen('TextStyle'):
			target = FcPatternBuild (0, FC_FAMILY, FcTypeString, _fontName, FC_PIXEL_SIZE, FcTypeDouble, _fontSize,
									 FC_WEIGHT, FcTypeInteger, ((_fontStyle & 1) ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL),
									 FC_SLANT, FcTypeInteger, ((_fontStyle & 2) ?  FC_SLANT_ITALIC : FC_SLANT_ROMAN),
									 FC_OUTLINE, FcTypeBool, ((_fontStyle & 8) ? true : false),
									 FC_WIDTH, FcTypeInteger, ( (_fontStyle & 32) ?  FC_WIDTH_CONDENSED : ((_fontStyle & 64) ?  FC_WIDTH_EXPANDED : FC_WIDTH_NORMAL) ),
									 FC_DPI, FcTypeDouble, (double) 72.0,
									 FC_SCALABLE, FcTypeBool, true,
									 FC_ANTIALIAS, FcTypeBool, ((_antiAliasing != 0) ? true : false), 
									 NULL);
		}

		FcDefaultSubstitute(target);
		
		// Have a matching pattern:
		if (_verbosity > 3) {
			fprintf(stderr, "libptbdrawtext_ftgl: Trying to find font that closely matches following specification:\n");
			FcPatternPrint(target);
		}

		// Perform font matching for the font in the default configuration (0) that best matches the
		// specified target pattern:
		FcPattern* matched = FcFontMatch(0, target, &result);
		if (result == FcResultNoMatch) {
			// Failed!
			if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig failed to find a matching font for family %s, size %f pts and style flags %i.\n", _fontName, (float) _fontSize, _fontStyle);
			FcPatternDestroy(target);
			return(1);
		}

		// Success: Extract relevant information for Freetype-2, the font filename and faceIndex:
		if (_verbosity > 3) {
			fprintf(stderr, "libptbdrawtext_ftgl: Best matching font which will be selected for drawing has following specs:\n");
			FcPatternPrint(matched);
		}

		// Retrieve font filename for matched font:
		FcChar8* localfontFileName = NULL;
		if (FcPatternGetString(matched, FC_FILE, 0, (FcChar8**) &localfontFileName) != FcResultMatch) {
			// Failed!
			if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig did not find filename for font with family %s, size %f pts and style flags %i.\n", _fontName, (float) _fontSize, _fontStyle);
			FcPatternDestroy(target);
			FcPatternDestroy(matched);
			return(1);
		}

		strcpy(_fontFileName, (char*) localfontFileName);

		// Retrieve faceIndex within fontfile:
		if (FcPatternGetInteger(matched, FC_INDEX, 0, &_faceIndex) != FcResultMatch)  {
			// Failed!
			if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig did not find faceIndex for font file %s, family %s, size %f pts and style flags %i.\n", _fontFileName, _fontName, (float) _fontSize, _fontStyle);
			FcPatternDestroy(target);
			FcPatternDestroy(matched);
			return(1);
		}

		// Release target pattern and matched pattern objects:
		FcPatternDestroy(target);
		FcPatternDestroy(matched);
	}
	else {
		// Use "raw" values as passed by calling client code:
		strcpy(_fontFileName, _fontName);
		_faceIndex = (int) _fontStyle;
	}
	
	// Load & Create new font and face object, based on current spec settings:
	// We directly use the Freetype library, so we can spec the faceIndex for selection of textstyle, which wouldn't be
	// possible with the higher-level OGLFT constructor...
    FT_Error error = FT_New_Face( OGLFT::Library::instance(), _fontFileName, _faceIndex, &ft_face );
	if (error) {
		if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not load face with index %i from font file %s.\n", _faceIndex, _fontFileName);
		return(1);
	}
	else {
		if (_verbosity > 3) fprintf(stderr, "libptbdrawtext_ftgl: Freetype loaded face %p with index %i from font file %s.\n", ft_face, _faceIndex, _fontFileName);
	}

	// Create FTGL face from Freetype face with given size and a 72 DPI resolution, aka _fontSize == pixelsize:
	if (_antiAliasing != 0) {
		faceT = new OGLFT::TranslucentTexture(ft_face, _fontSize, 72);
		// Test the created face to make sure it will work correctly:
		if (!faceT->isValid()) {
			if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not recognize %s as a font file.\n", _fontName);
			return(1);
		}
	}
	else {
		faceM = new OGLFT::MonochromeTexture(ft_face, _fontSize, 72);
		// Test the created face to make sure it will work correctly:
		if (!faceM->isValid()) {
			if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not recognize %s as a font file.\n", _fontName);
			return(1);
		}
	}

	// Ready!
	_needsRebuild = false;
	
	return(0);
}
Esempio 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;
}
Esempio n. 6
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);
}
Esempio n. 7
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;
}
Esempio n. 8
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 */
}
Esempio n. 9
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;
}
Esempio n. 10
0
FcFontSet *fcinfo_families_index(const FcPattern *filter)
{
  int unused_int, f, nfamilies;

  FcPattern *pattern, *match;
  FcFontSet *fontset, *tmp, 
            *families;
  FcResult r;

  FcChar8 *family, *next_family, *normal_style, *style;

  FcInit();
  pattern = FcPatternDuplicate(filter);
  fontset = fcinfo(NULL, filter, FcFalse, 5,
                   FC_FAMILY,
                   FC_STYLE,
                   FC_LANG,/* fonts like Misc Fixed need 
                              to be sorted by LANG (subset-like) */
                   FC_PIXEL_SIZE,
                   FC_FILE); /* for identifying the best font in 
                                FC_LANG terms */
  if (fontset->nfont == 0)
    return fontset;

  tmp = fcinfo_match(fontset, pattern);
  FcFontSetDestroy(fontset);
  fontset = tmp;

  if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR);
  if (FcPatternGetInteger(pattern, FC_SLANT, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
  if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &unused_int) != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WIDTH, FC_WIDTH_NORMAL);

  /* choose 'normal' styles according to pattern */
  families = FcFontSetCreate();
  nfamilies = 0;
  for (f = 0; f < fontset->nfont; )
  {
    assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                        LANG_EN, &family)
           == FcResultMatch);

    FcPatternDel(pattern, FC_FAMILY);
    FcPatternAddString(pattern, FC_FAMILY, family);
    match = FcFontSetMatch(NULL, &fontset, 1, pattern, &r);
    assert(fcinfo_get_translated_string(match, FC_STYLE, LANG_EN, &normal_style)
            == FcResultMatch);
    do
    {
      assert(fcinfo_get_translated_string(fontset->fonts[f], FC_STYLE, 
                                          LANG_EN, &style)
             == FcResultMatch);
      
      if (FcStrCmpIgnoreCase(style, normal_style) == 0)
        FcFontSetAdd(families, FcPatternDuplicate(fontset->fonts[f]));

      if (++f == fontset->nfont)
        break;

      assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, 
                                          LANG_EN, &next_family)
             == FcResultMatch);
    }
    while (FcStrCmpIgnoreCase(family, next_family) == 0);
    nfamilies++;
  }

  FcPatternDestroy(pattern);
  FcFontSetDestroy(fontset);

  return families;
}
Esempio n. 11
0
static int pattern_compare (const void *arg1, const void *arg2, void *arg3)
{
  const FcPattern *p1 = *(FcPattern * const *)arg1;
  const FcPattern *p2 = *(FcPattern * const *)arg2;
  const char **el = (const char **)arg3;
  FcChar8 *string1, *string2;
  int int1, int2;
  FcBool bool1, bool2;
  FcLangSet *langset1, *langset2;
  double double1, double2;
  int ret = 0;

  while (*el)
  {
    /* string */
    if (!strcmp(*el, FC_FAMILY) || !strcmp(*el, FC_STYLE) || !strcmp(*el, FC_FONTFORMAT))
    {
      if (FcPatternGetString (p1, *el, 0, &string1) == FcResultMatch &&
	  FcPatternGetString (p2, *el, 0, &string2) == FcResultMatch) 
        ret = strings_compare((char *)string1, (char *)string2);
    }
    /* integer */
    else if (!strcmp(*el, FC_WEIGHT) || !strcmp(*el, FC_WIDTH) ||
	     !strcmp(*el, FC_SLANT) || !strcmp(*el, FC_SPACING))
    {
      if (FcPatternGetInteger(p1, *el, 0, &int1) == FcResultMatch && 
	  FcPatternGetInteger(p2, *el, 0, &int2) == FcResultMatch)
	ret = int2 - int1;
    }
    /* bool */
    else if (!strcmp(*el, FC_SCALABLE) || !strcmp(*el, FC_DECORATIVE))
    {
      if (FcPatternGetBool(p1, *el, 0, &bool1) == FcResultMatch &&
	  FcPatternGetBool(p1, *el, 0, &bool2) == FcResultMatch)
       ret = bool2 - bool1;
    }
    /* double */
    else if (!strcmp(*el, FC_PIXEL_SIZE))
    {
      if (FcPatternGetDouble(p1, *el, 0, &double1) == FcResultMatch &&
	  FcPatternGetDouble(p2, *el, 0, &double2) == FcResultMatch)
	ret = fabs(double1 - SIZE_MEAN) - fabs(double2 - SIZE_MEAN);
    }
    /* lang set */
    else if (!strcmp(*el, FC_LANG))
    {
      /* to choose size of bitmap font which supports widest range of langs */
      /* maybe charset would be better? */
      if (FcPatternGetLangSet(p1, *el, 0, &langset1) == FcResultMatch &&
	  FcPatternGetLangSet(p2, *el, 0, &langset2) == FcResultMatch)
      {
        ret = 0;
	if (FcLangSetContains(langset1, langset2))
	  ret = -1;
	if (FcLangSetContains(langset2, langset1))
        {
          if (ret == -1)
            ret = 0; /* langset1 <= langset2 & langset1 >= langset2 */
          else
    	    ret = 1;
        }
      }
    }

    if (ret)
      break;

    el++;
  }

  return ret;
}
bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
                                                  SkFontStyle style,
                                                  FontIdentity* outIdentity,
                                                  SkString* outFamilyName,
                                                  SkFontStyle* outStyle) {
    SkString familyStr(familyName ? familyName : "");
    if (familyStr.size() > kMaxFontFamilyLength) {
        return false;
    }

    SkAutoMutexAcquire ac(mutex_);

    FcPattern* pattern = FcPatternCreate();

    if (familyName) {
        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
    }
    fcpattern_from_skfontstyle(style, pattern);

    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);

    FcConfigSubstitute(nullptr, 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 nullptr 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().

    const char* post_config_family = get_name(pattern, FC_FAMILY);
    if (!post_config_family) {
        // we can just continue with an empty name, e.g. default font
        post_config_family = "";
    }

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

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

    FcPatternDestroy(pattern);

    // From here out we just extract our results from 'match'

    post_config_family = get_name(match, FC_FAMILY);
    if (!post_config_family) {
        FcFontSetDestroy(font_set);
        return false;
    }

    const char* c_filename = get_name(match, FC_FILE);
    if (!c_filename) {
        FcFontSetDestroy(font_set);
        return false;
    }

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

    FcFontSetDestroy(font_set);

    if (outIdentity) {
        outIdentity->fTTCIndex = face_index;
        outIdentity->fString.set(c_filename);
    }
    if (outFamilyName) {
        outFamilyName->set(post_config_family);
    }
    if (outStyle) {
        *outStyle = skfontstyle_from_fcpattern(match);
    }
    return true;
}
Esempio n. 13
0
int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path)
{
#ifdef HAVE_FONTCONFIG
    unix_fontenum_t* state = (unix_fontenum_t *)enum_state;
    FcChar8 *file_fc = NULL;
    FcChar8 *family_fc = NULL;
    int outline_fc, slant_fc, weight_fc;
    FcPattern *font;
    FcResult result;

    if (state == NULL) {
        return 0;   /* gp_enumerate_fonts_init failed for some reason */
    }

    if (state->index == state->font_list->nfont) {
        return 0; /* we've run out of fonts */
    }

    /* Bits of the following were borrowed from Red Hat's
     * fontconfig patch for Ghostscript 7 */
    font = state->font_list->fonts[state->index];

    result = FcPatternGetString (font, FC_FAMILY, 0, &family_fc);
    if (result != FcResultMatch || family_fc == NULL) {
        dlprintf ("DEBUG: FC_FAMILY mismatch\n");
        return 0;
    }

    result = FcPatternGetString (font, FC_FILE, 0, &file_fc);
    if (result != FcResultMatch || file_fc == NULL) {
        dlprintf ("DEBUG: FC_FILE mismatch\n");
        return 0;
    }

    result = FcPatternGetBool (font, FC_OUTLINE, 0, &outline_fc);
    if (result != FcResultMatch) {
        dlprintf1 ("DEBUG: FC_OUTLINE failed to match on %s\n", (char*)family_fc);
        return 0;
    }

    result = FcPatternGetInteger (font, FC_SLANT, 0, &slant_fc);
    if (result != FcResultMatch) {
        dlprintf ("DEBUG: FC_SLANT didn't match\n");
        return 0;
    }

    result = FcPatternGetInteger (font, FC_WEIGHT, 0, &weight_fc);
    if (result != FcResultMatch) {
        dlprintf ("DEBUG: FC_WEIGHT didn't match\n");
        return 0;
    }

    /* Gross hack to work around Fontconfig's inability to tell
     * us the font's PostScript name - generate it ourselves.
     * We must free the memory allocated here next time around. */
    makePSFontName((char *)family_fc, weight_fc, slant_fc,
        (char *)&state->name, sizeof(state->name));
    *fontname = (char *)&state->name;

    /* return the font path straight out of fontconfig */
    *path = (char*)file_fc;

    state->index ++;
    return 1;
#else
    return 0;
#endif
}
Esempio n. 14
0
/**
 * \brief Low-level font selection.
 * \param priv private data
 * \param family font family
 * \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(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
			  uint32_t code)
{
	FcBool rc;
	FcResult result;
	FcPattern *pat = 0, *rpat = 0;
	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* fset = 0;
	int curf;
	char* retval = 0;
	int family_cnt;
	
	*index = 0;

	pat = FcPatternCreate();
	if (!pat)
		goto error;
	
	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);
		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;

	fset = FcFontSort(priv->config, pat, FcTrue, NULL, &result);

	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 (FC_VERSION >= 20297)
	// 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);
#endif

	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);

	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 (!(r_family && strcasecmp((const char*)r_family, family) == 0) &&
	    !(r_fullname && strcasecmp((const char*)r_fullname, family) == 0))
		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne,
		       (const char*)(r_fullname ? r_fullname : r_family), family);

	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;

	mp_msg(MSGT_ASS, MSGL_V, "[ass] Font info: family '%s', style '%s', fullname '%s',"
	       " slant %d, weight %d%s\n",
	       (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 (fset) FcFontSetDestroy(fset);
	return retval;
}
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;
}
Esempio n. 16
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;
}
Esempio n. 17
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);
}
Esempio n. 18
0
void SkScalerContext_CairoFT::parsePattern(FcPattern* pattern)
{
    FcBool antialias, autohint, bitmap, embolden, hinting, vertical;

    if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && autohint) {
        fRec.fFlags |= SkScalerContext::kForceAutohinting_Flag;
    }
    if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == FcResultMatch && bitmap) {
        fRec.fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag;
    }
    if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && embolden) {
        fRec.fFlags |= SkScalerContext::kEmbolden_Flag;
    }
    if (FcPatternGetBool(pattern, FC_VERTICAL_LAYOUT, 0, &vertical) == FcResultMatch && vertical) {
        fRec.fFlags |= SkScalerContext::kVertical_Flag;
    }

    if (fRec.fMaskFormat != SkMask::kBW_Format &&
        (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch || antialias)) {
        int rgba;
        if (!isLCD(fRec) ||
            FcPatternGetInteger(pattern, FC_RGBA, 0, &rgba) != FcResultMatch) {
            rgba = FC_RGBA_UNKNOWN;
        }
        switch (rgba) {
        case FC_RGBA_RGB:
            break;
        case FC_RGBA_BGR:
            fRec.fFlags |= SkScalerContext::kLCD_BGROrder_Flag;
            break;
        case FC_RGBA_VRGB:
            fRec.fFlags |= SkScalerContext::kLCD_Vertical_Flag;
            break;
        case FC_RGBA_VBGR:
            fRec.fFlags |= SkScalerContext::kLCD_Vertical_Flag |
                           SkScalerContext::kLCD_BGROrder_Flag;
            break;
        default:
            fRec.fMaskFormat = SkMask::kA8_Format;
            break;
        }

        int filter;
        if (isLCD(fRec)) {
            if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) != FcResultMatch) {
                filter = FC_LCD_LEGACY;
            }
            switch (filter) {
            case FC_LCD_NONE:
                fLcdFilter = FT_LCD_FILTER_NONE;
                break;
            case FC_LCD_DEFAULT:
                fLcdFilter = FT_LCD_FILTER_DEFAULT;
                break;
            case FC_LCD_LIGHT:
                fLcdFilter = FT_LCD_FILTER_LIGHT;
                break;
            case FC_LCD_LEGACY:
            default:
                fLcdFilter = FT_LCD_FILTER_LEGACY;
                break;
            }
        }
    } else {
        fRec.fMaskFormat = SkMask::kBW_Format;
    }

    if (fRec.getHinting() != SkPaint::kNo_Hinting &&
        (FcPatternGetBool(pattern, FC_HINTING, 0, &hinting) != FcResultMatch || hinting)) {
        int hintstyle;
        if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) {
            hintstyle = FC_HINT_FULL;
        }
        switch (hintstyle) {
        case FC_HINT_NONE:
            fRec.setHinting(SkPaint::kNo_Hinting);
            break;
        case FC_HINT_SLIGHT:
            fRec.setHinting(SkPaint::kSlight_Hinting);
            break;
        case FC_HINT_MEDIUM:
        default:
            fRec.setHinting(SkPaint::kNormal_Hinting);
            break;
        case FC_HINT_FULL:
            fRec.setHinting(SkPaint::kFull_Hinting);
            break;
        }
    }
}
Esempio n. 19
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);
}
Esempio n. 20
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 */
}
Esempio n. 21
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;
}
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);
}
Esempio n. 23
0
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
{
	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];
	seprintf(lang, lastof(lang), ":lang=%s", language_isocode);
	char *split = strchr(lang, '_');
	if (split != NULL) *split = '\0';

	/* First create a pattern to match the wanted language. */
	FcPattern *pat = FcNameParse((FcChar8*)lang);
	/* We only want to know the filename. */
	FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, NULL);
	/* Get the list of filenames matching the wanted language. */
	FcFontSet *fs = FcFontList(NULL, pat, os);

	/* We don't need these anymore. */
	FcObjectSetDestroy(os);
	FcPatternDestroy(pat);

	if (fs != NULL) {
		int best_weight = -1;
		const char *best_font = NULL;

		for (int i = 0; i < fs->nfont; i++) {
			FcPattern *font = fs->fonts[i];

			FcChar8 *file = NULL;
			FcResult res = FcPatternGetString(font, FC_FILE, 0, &file);
			if (res != FcResultMatch || file == NULL) {
				continue;
			}

			/* Get a font with the right spacing .*/
			int value = 0;
			FcPatternGetInteger(font, FC_SPACING, 0, &value);
			if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue;

			/* Do not use those that explicitly say they're slanted. */
			FcPatternGetInteger(font, FC_SLANT, 0, &value);
			if (value != 0) continue;

			/* We want the fatter font as they look better at small sizes. */
			FcPatternGetInteger(font, FC_WEIGHT, 0, &value);
			if (value <= best_weight) continue;

			callback->SetFontNames(settings, (const char*)file);

			bool missing = callback->FindMissingGlyphs(NULL);
			DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");

			if (!missing) {
				best_weight = value;
				best_font   = (const char *)file;
			}
		}

		if (best_font != NULL) {
			ret = true;
			callback->SetFontNames(settings, best_font);
			InitFreeType(callback->Monospace());
		}

		/* Clean up the list of filenames. */
		FcFontSetDestroy(fs);
	}

	FcFini();
	return ret;
}
Esempio n. 24
0
static int load_font_fontconfig(AVFilterContext *ctx)
{
    DrawTextContext *s = ctx->priv;
    FcConfig *fontconfig;
    FcPattern *pat, *best;
    FcResult result = FcResultMatch;
    FcChar8 *filename;
    int index;
    double size;
    int err = AVERROR(ENOENT);

    fontconfig = FcInitLoadConfigAndFonts();
    if (!fontconfig) {
        av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
        return AVERROR_UNKNOWN;
    }
    pat = FcNameParse(s->fontfile ? s->fontfile :
                          (uint8_t *)(intptr_t)"default");
    if (!pat) {
        av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
        return AVERROR(EINVAL);
    }

    FcPatternAddString(pat, FC_FAMILY, s->font);
    if (s->fontsize)
        FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize);

    FcDefaultSubstitute(pat);

    if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
        av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */
        FcPatternDestroy(pat);
        return AVERROR(ENOMEM);
    }

    best = FcFontMatch(fontconfig, pat, &result);
    FcPatternDestroy(pat);

    if (!best || result != FcResultMatch) {
        av_log(ctx, AV_LOG_ERROR,
               "Cannot find a valid font for the family %s\n",
               s->font);
        goto fail;
    }

    if (
        FcPatternGetInteger(best, FC_INDEX, 0, &index   ) != FcResultMatch ||
        FcPatternGetDouble (best, FC_SIZE,  0, &size    ) != FcResultMatch) {
        av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
        return AVERROR(EINVAL);
    }

    if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
        av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
               s->font);
        goto fail;
    }

    av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
    if (!s->fontsize)
        s->fontsize = size + 0.5;

    err = load_font_file(ctx, filename, index);
    if (err)
        return err;
    FcConfigDestroy(fontconfig);
fail:
    FcPatternDestroy(best);
    return err;
}
Esempio n. 25
0
static void populateFromPattern(FcPattern *pattern)
{
    QString familyName;
    QString familyNameLang;
    FcChar8 *value = 0;
    int weight_value;
    int slant_value;
    int spacing_value;
    int width_value;
    FcChar8 *file_value;
    int indexValue;
    FcChar8 *foundry_value;
    FcChar8 *style_value;
    FcBool scalable;
    FcBool antialias;

    if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
        return;

    familyName = QString::fromUtf8((const char *)value);

    if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
        familyNameLang = QString::fromUtf8((const char *)value);

    slant_value = FC_SLANT_ROMAN;
    weight_value = FC_WEIGHT_REGULAR;
    spacing_value = FC_PROPORTIONAL;
    file_value = 0;
    indexValue = 0;
    scalable = FcTrue;


    if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
        slant_value = FC_SLANT_ROMAN;
    if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
        weight_value = FC_WEIGHT_REGULAR;
    if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
        width_value = FC_WIDTH_NORMAL;
    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
        spacing_value = FC_PROPORTIONAL;
    if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
        file_value = 0;
    if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
        indexValue = 0;
    if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
        scalable = FcTrue;
    if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
        foundry_value = 0;
    if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
        style_value = 0;
    if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
        antialias = true;

    QSupportedWritingSystems writingSystems;
    FcLangSet *langset = 0;
    FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
    if (res == FcResultMatch) {
        bool hasLang = false;
#if FC_VERSION >= 20297
        FcChar8 *cap = Q_NULLPTR;
        FcResult capRes = FcResultNoMatch;
#endif
        for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
            const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j];
            if (lang) {
                FcLangResult langRes = FcLangSetHasLang(langset, lang);
                if (langRes != FcLangDifferentLang) {
#if FC_VERSION >= 20297
                    if (*capabilityForWritingSystem[j] && requiresOpenType(j)) {
                        if (cap == Q_NULLPTR)
                            capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap);
                        if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0)
                            continue;
                    }
#endif
                    writingSystems.setSupported(QFontDatabase::WritingSystem(j));
                    hasLang = true;
                }
            }
        }
        if (!hasLang)
            // none of our known languages, add it to the other set
            writingSystems.setSupported(QFontDatabase::Other);
    } 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);
    }

    FontFile *fontFile = new FontFile;
    fontFile->fileName = QString::fromLocal8Bit((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);
    // Note: weight should really be an int but registerFont incorrectly uses an enum
    QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));

    double pixel_size = 0;
    if (!scalable)
        FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);

    bool fixedPitch = spacing_value >= FC_MONO;
    // Note: stretch should really be an int but registerFont incorrectly uses an enum
    QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
    QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
    QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
//        qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;

    for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) {
        const QString altFamilyName = QString::fromUtf8((const char *)value);
        // Extra family names can be aliases or subfamilies.
        // If it is a subfamily, register it as a separate font, so only members of the subfamily are
        // matched when the subfamily is requested.
        QString altStyleName;
        if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch)
            altStyleName = QString::fromUtf8((const char *)value);
        else
            altStyleName = styleName;

        QString altFamilyNameLang;
        if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch)
            altFamilyNameLang = QString::fromUtf8((const char *)value);
        else
            altFamilyNameLang = familyNameLang;

        if (familyNameLang == altFamilyNameLang && altStyleName != styleName) {
            FontFile *altFontFile = new FontFile(*fontFile);
            QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile);
        } else {
            QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
        }
    }

}
Esempio n. 26
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;
}
Esempio n. 27
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);
}
Esempio n. 28
0
static void
apply_xft_settings (struct x_display_info *dpyinfo,
                    int send_event_p,
                    struct xsettings *settings)
{
#ifdef HAVE_XFT
  FcPattern *pat;
  struct xsettings oldsettings;
  int changed = 0;

  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;
      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;
      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;
    }

  /* 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;
      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;
      oldsettings.hintstyle = settings->hintstyle;
    }
#endif

  if ((settings->seen & SEEN_DPI) != 0 && oldsettings.dpi != settings->dpi
      && settings->dpi > 0)
    {
      Lisp_Object frame, tail;

      FcPatternDel (pat, FC_DPI);
      FcPatternAddDouble (pat, FC_DPI, settings->dpi);
      ++changed;
      oldsettings.dpi = settings->dpi;

      /* Change the DPI on this display and all frames on the display.  */
      dpyinfo->resy = dpyinfo->resx = settings->dpi;
      FOR_EACH_FRAME (tail, frame)
        if (FRAME_X_P (XFRAME (frame))
            && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
          XFRAME (frame)->resy = XFRAME (frame)->resx = settings->dpi;
    }