Beispiel #1
0
// also handle an xlfd with %d for size?
static char*
makeFontOfSize(char *font, int size, char *fallback)
{
    FcPattern *pattern;
    char *result;

    if (font[0]=='-') {
        char *fname;

        fname = fixXLFD(font, size);
        pattern = XftXlfdParse(fname, False, False);
        wfree(fname);
    } else {
        pattern = FcNameParse(font);
    }

    //FcPatternPrint(pattern);
    if (size > 0) {
        FcPatternDel(pattern, "pixelsize");
        FcPatternAddDouble(pattern, "pixelsize", (double)size);
    } else if (size==0 && !hasProperty(pattern, "size") &&
               !hasProperty(pattern, "pixelsize")) {
        FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE);
    }

    if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) {
        FcPatternAddString(pattern, "family", fallback);
    }

    result = FcNameUnparse(pattern);
    FcPatternDestroy(pattern);

    return result;
}
Beispiel #2
0
MenuGraphic::MenuGraphic(Menu* menu) :
    menu_(menu) {
        const char* fontFamily = "Anonymous Pro";
        const char* fontStyle = "Bold";
        const char* fontSpacing = "Monospace";
        char* font;
        FcPattern* fontPattern = FcPatternCreate();
        FcResult fontResult = FcResultMatch;
        int fontSize = 74;
        FcPatternAddString(fontPattern, FC_FAMILY, 
                (const FcChar8*) fontFamily);
        FcPatternAddDouble(fontPattern, FC_SIZE, fontSize);
        FcPatternAddString(fontPattern, FC_SPACING, 
                (const FcChar8*) fontSpacing);
        FcPatternAddString(fontPattern, FC_STYLE, 
                (const FcChar8*) fontStyle);
        FcDefaultSubstitute(fontPattern);
        FcPattern* fontMatch = FcFontMatch(NULL, fontPattern, &fontResult);
        FcPatternGetString(fontMatch, FC_FILE, 0, (FcChar8**) &font);
        for (int i = 0; i < Menu::NUM_MENU; ++i) {
            // Create a new SubmenuGraphic for each Submenu
            menuGraphics_[i] = new SubmenuGraphic(menu->getMenu(i));
            Submenu* submenu = menu->getMenu(i);
            // Add buttons and labels
            for (std::vector<GuiElement*>::iterator j = 
                    submenu->buttons.begin(); j < submenu->buttons.end(); ++j) {
                labels_.push_back(new Label(font, ((Button*) (*j))->getText(), 
                            fontSize, .5, .1));
                menuGraphics_[i]->addButton((*j), labels_.back(), 
                        (*j)->isSelected());
            }
        }
}
Beispiel #3
0
FcPattern *fcinfo_get_font(const FcChar8 *request)
{
  FcPattern *pattern, *match;
  FcResult r;
  FcChar8 *string;
  int integer;
  double double_num;

  pattern = fcinfo_name_parse((FcChar8 *) request);
  if (FcPatternGetString(pattern, FC_FAMILY, 0, &string)
      != FcResultMatch)
    FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *)"sans-serif");
  if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &double_num)
      != FcResultMatch)
    FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12.0);
  if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &integer)
      != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR);
  if (FcPatternGetInteger(pattern, FC_SLANT, 0, &integer)
      != FcResultMatch)
    FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
  if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &integer)
      != FcResultMatch)
    FcPatternAddInteger(pattern, FC_WIDTH, FC_WIDTH_NORMAL);

  FcConfigSubstitute(NULL, pattern, FcMatchPattern);
  FcDefaultSubstitute(pattern);
  match = FcFontMatch(0, pattern, &r);
  assert(r == FcResultMatch);

  FcPatternDestroy(pattern);
  return match;
}
// ----------------------------------------- font_manager_match_description ---
char *
font_manager_match_description( font_manager_t * self,
                                const char * family,
                                const float size,
                                const int bold,
                                const int italic )
{
// Use of fontconfig is disabled by default.
#if 1
    return 0;
#else
#  if defined _WIN32 || defined _WIN64
      fprintf( stderr, "\"font_manager_match_description\" not implemented for windows.\n" );
      return 0;
#  endif
    char *filename = 0;
    int weight = FC_WEIGHT_REGULAR;
    int slant = FC_SLANT_ROMAN;
    if ( bold )
    {
        weight = FC_WEIGHT_BOLD;
    }
    if( italic )
    {
        slant = FC_SLANT_ITALIC;
    }
    FcInit();
    FcPattern *pattern = FcPatternCreate();
    FcPatternAddDouble( pattern, FC_SIZE, size );
    FcPatternAddInteger( pattern, FC_WEIGHT, weight );
    FcPatternAddInteger( pattern, FC_SLANT, slant );
    FcPatternAddString( pattern, FC_FAMILY, (FcChar8*) family );
    FcConfigSubstitute( 0, pattern, FcMatchPattern );
    FcDefaultSubstitute( pattern );
    FcResult result;
    FcPattern *match = FcFontMatch( 0, pattern, &result );
    FcPatternDestroy( pattern );

    if ( !match )
    {
        fprintf( stderr, "fontconfig error: could not match family '%s'", family );
        return 0;
    }
    else
    {
        FcValue value;
        FcResult result = FcPatternGet( match, FC_FILE, 0, &value );
        if ( result )
        {
            fprintf( stderr, "fontconfig error: could not match family '%s'", family );
        }
        else
        {
            filename = strdup( (char *)(value.u.s) );
        }
    }
    FcPatternDestroy( match );
    return filename;
#endif
}
Beispiel #5
0
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
{
    // The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm)
    // says that we must find an exact match for font family, slant (italic or oblique can be used)
    // and font weight (we only match bold/non-bold here).
    RefPtr<FcPattern> pattern = adoptRef(FcPatternCreate());
    String familyNameString(getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family));
    if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.utf8().data())))
        return 0;

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

    // The strategy is originally from Skia (src/ports/SkFontHost_fontconfig.cpp):

    // Allow Fontconfig to do pre-match substitution. Unless we are accessing a "fallback"
    // family like "sans," this is the only time we allow Fontconfig to substitute one
    // family name for another (i.e. if the fonts are aliased to each other).
    FcConfigSubstitute(0, pattern.get(), FcMatchPattern);
    FcDefaultSubstitute(pattern.get());

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

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

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

    // If Fontconfig gave use a different font family than the one we requested, we should ignore it
    // and allow WebCore to give us the next font on the CSS fallback list. The only exception is if
    // this family name is a commonly used generic family.
    if (!equalIgnoringCase(familyNameAfterConfiguration, familyNameAfterMatching)
            && !(equalIgnoringCase(familyNameString, "sans") || equalIgnoringCase(familyNameString, "sans-serif")
                 || equalIgnoringCase(familyNameString, "serif") || equalIgnoringCase(familyNameString, "monospace")
                 || equalIgnoringCase(familyNameString, "fantasy") || equalIgnoringCase(familyNameString, "cursive")))
        return 0;

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

    return platformData;
}
Beispiel #6
0
static void
xftfont_fix_match (FcPattern *pat, FcPattern *match)
{
  /*  These values are not used for matching (except antialias), but for
      rendering, so make sure they are carried over to the match.
      We also put antialias here because most fonts are antialiased, so
      the match will have antialias true.  */

  FcBool b = FcTrue;
  int i;
  double dpi;

  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
  if (! b)
    {
      FcPatternDel (match, FC_ANTIALIAS);
      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
    }
  FcPatternGetBool (pat, FC_HINTING, 0, &b);
  if (! b)
    {
      FcPatternDel (match, FC_HINTING);
      FcPatternAddBool (match, FC_HINTING, FcFalse);
    }
#ifndef FC_HINT_STYLE
# define FC_HINT_STYLE "hintstyle"
#endif
  if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
    {
      FcPatternDel (match, FC_HINT_STYLE);
      FcPatternAddInteger (match, FC_HINT_STYLE, i);
    }
#ifndef FC_LCD_FILTER
  /* Older fontconfig versions don't have FC_LCD_FILTER. */
#define FC_LCD_FILTER "lcdfilter"
#endif
  if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
    {
      FcPatternDel (match, FC_LCD_FILTER);
      FcPatternAddInteger (match, FC_LCD_FILTER, i);
    }
  if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
    {
      FcPatternDel (match, FC_RGBA);
      FcPatternAddInteger (match, FC_RGBA, i);
    }
  if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
    {
      FcPatternDel (match, FC_DPI);
      FcPatternAddDouble (match, FC_DPI, dpi);
    }
}
static cairo_scaled_font_t *
create_scaled_font (cairo_t * cr)
{
    FcPattern *pattern, *resolved;
    FcResult result;
    cairo_font_face_t *font_face;
    cairo_scaled_font_t *scaled_font;
    cairo_font_options_t *font_options;
    cairo_matrix_t font_matrix, ctm;
    double pixel_size;

    font_options = cairo_font_options_create ();

    cairo_get_font_options (cr, font_options);

    pattern = FcPatternCreate ();

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

    cairo_ft_font_options_substitute (font_options, pattern);

    FcDefaultSubstitute (pattern);
    resolved = FcFontMatch (NULL, pattern, &result);

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

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

    font_face = cairo_ft_font_face_create_for_pattern (resolved);

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

    cairo_get_matrix (cr, &ctm);

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

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

    return scaled_font;
}
void SkScalerContext_CairoFT::resolvePattern(FcPattern* pattern)
{
    if (!pattern) {
        return;
    }
    FcValue value;
    if (FcPatternGet(pattern, FC_PIXEL_SIZE, 0, &value) == FcResultNoMatch) {
        SkAutoTUnref<FcPattern> scalePattern(FcPatternDuplicate(pattern));
        if (scalePattern &&
            FcPatternAddDouble(scalePattern, FC_PIXEL_SIZE, fScaleY) &&
            FcConfigSubstitute(nullptr, scalePattern, FcMatchPattern)) {
            FcDefaultSubstitute(scalePattern);
            FcResult result;
            SkAutoTUnref<FcPattern> resolved(FcFontMatch(nullptr, scalePattern, &result));
            if (resolved) {
                parsePattern(resolved);
                return;
            }
        }
    }
    parsePattern(pattern);
}
Beispiel #9
0
static XftFont* getfont(XftFont **font, uint32_t ch)
{
    XftFont *first = font[0];
    if(!FcCharSetHasChar(charset, ch)) {
        return first;
    }

    while(*font) {
        if(XftGlyphExists(display, *font, ch)) {
            return *font;
        }
        font++;
    }

    FcResult result;
    int i;
    for(i = 0; i != fs->nfont; i++) {
        FcCharSet *cs;
        result = FcPatternGetCharSet(fs->fonts[i], FC_CHARSET, 0, &cs);
        if(FcCharSetHasChar(cs, ch)) {
            FcPattern *p = FcPatternDuplicate(fs->fonts[i]), *pp;

            double size;
            if(!FcPatternGetDouble(first->pattern, FC_PIXEL_SIZE, 0, &size)) {
                FcPatternAddDouble(p, FC_PIXEL_SIZE, size);
            }

            pp = XftFontMatch(display, screen, p, &result);
            *font = XftFontOpenPattern(display, pp);
            FcPatternDestroy(p);
            return *font;
        }
    }

    //should never happen
    return first;
}
Beispiel #10
0
FcPattern *
FcNameParse (const FcChar8 *name)
{
    FcChar8		*save;
    FcPattern		*pat;
    double		d;
    FcChar8		*e;
    FcChar8		delim;
    FcValue		v;
    FcMatrix		m;
    const FcObjectType	*t;
    const FcConstant	*c;

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

    for (;;)
    {
	name = FcNameFindNext (name, "-,:", save, &delim);
	if (save[0])
	{
	    if (!FcPatternAddString (pat, FC_FAMILY, save))
		goto bail2;
	}
	if (delim != ',')
	    break;
    }
    if (delim == '-')
    {
	for (;;)
	{
	    name = FcNameFindNext (name, "-,:", save, &delim);
	    d = strtod ((char *) save, (char **) &e);
	    if (e != save)
	    {
		if (!FcPatternAddDouble (pat, FC_SIZE, d))
		    goto bail2;
	    }
	    if (delim != ',')
		break;
	}
    }
    while (delim == ':')
    {
	name = FcNameFindNext (name, "=_:", save, &delim);
	if (save[0])
	{
	    if (delim == '=' || delim == '_')
	    {
		t = FcNameGetObjectType ((char *) save);
		for (;;)
		{
		    name = FcNameFindNext (name, ":,", save, &delim);
		    if (t)
		    {
			v = FcNameConvert (t->type, save, &m);
			if (!FcPatternAdd (pat, t->object, v, FcTrue))
			{
			    switch (v.type) {
			    case FcTypeCharSet:
				FcCharSetDestroy ((FcCharSet *) v.u.c);
				break;
			    case FcTypeLangSet:
				FcLangSetDestroy ((FcLangSet *) v.u.l);
				break;
			    default:
				break;
			    }
			    goto bail2;
			}
			switch (v.type) {
			case FcTypeCharSet:
			    FcCharSetDestroy ((FcCharSet *) v.u.c);
			    break;
			case FcTypeLangSet:
			    FcLangSetDestroy ((FcLangSet *) v.u.l);
			    break;
			default:
			    break;
			}
		    }
		    if (delim != ',')
			break;
		}
	    }
	    else
	    {
		if ((c = FcNameGetConstant (save)))
		{
		    if (!FcPatternAddInteger (pat, c->object, c->value))
			goto bail2;
		}
	    }
	}
    }

    free (save);
    return pat;

bail2:
    FcPatternDestroy (pat);
bail1:
    free (save);
bail0:
    return 0;
}
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_pattern(0)
    , m_fallbacks(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) {
        LOG(FontEngine, "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) {
        LOG(FontEngine, "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)) {
        LOG(FontEngine, "fail to open fonti %s with index %d (error = 0x%x)\n", filename, id, 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);
}
Beispiel #12
0
FcFontSet * fcinfo_match(FcFontSet *fontset, const FcPattern *filter)
{
  int f;

  FcFontSet *result;

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

  double size;

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

  FcInit();

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

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

     we want only one card for family,style pair

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

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

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

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

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

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

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

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

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

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

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

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

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

        f++;
      }
    }

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

  if (match)
    FcPatternDestroy(match);
  return result;
}
Beispiel #13
0
int face_from_options(lua_State* L) {
  FcChar8 * font_path, * fullname, * familyname;
  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";
  const char *style = "";

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

  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, "filename");
  lua_gettable(L, -2);
  if (lua_isstring(L, -1)) {
    font_path = lua_tostring(L, -1);
    lua_pop(L,1);
    lua_newtable(L);
    lua_pushstring(L, "filename");
    lua_pushstring(L, (char*)font_path);
    lua_settable(L, -3);
    goto done_match;
  }
  lua_pop(L,1);

  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 FC_VERSION >= 21191
    newWeight = FcWeightFromOpenType(newWeight);
#else
    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;
#endif
    weight = newWeight;
  }
  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)) {
    style = lua_tostring(L, -1);
    if (strcasestr(style,"italic")) {
      slant = FC_SLANT_ITALIC;
      style = "\0";
    } else if (strcasestr(style, "oblique")) {
      slant = FC_SLANT_OBLIQUE;
      style = "\0";
    }
  }
  lua_pop(L,1);

  p = FcPatternCreate();

  FcPatternAddString (p, FC_FAMILY, (FcChar8*)(family));
  FcPatternAddDouble (p, FC_SIZE, pointSize);
  if (strlen(style) > 0) {
    FcPatternAddString (p, FC_STYLE, style);
  } else {
    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");

  FcConfigSubstitute (NULL, p, FcMatchFont);
  FcDefaultSubstitute (p);
  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);
  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, &familyname) != 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*)(familyname));
  lua_settable(L, -3);

  if (FcPatternGetString (matched, FC_FULLNAME, 0, &fullname) == FcResultMatch) {
    lua_pushstring(L, "fullname");
    lua_pushstring(L, (char*)(fullname));
    lua_settable(L, -3);
  }

  FcPatternDestroy (matched);
  FcPatternDestroy (p);

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

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

  return 1;
}
Beispiel #14
0
static void
apply_xft_settings (struct x_display_info *dpyinfo,
                    struct xsettings *settings)
{
#ifdef HAVE_XFT
  FcPattern *pat;
  struct xsettings oldsettings;
  bool changed = false;

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

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

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

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

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

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

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

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

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

    }
  else
    FcPatternDestroy (pat);
#endif /* HAVE_XFT */
}
Beispiel #15
0
/***
 * \brief Selects a font matching family, bold, italic provided
 ***/
char* FontConfig_Select( filter_t *p_filter, const char* family,
                          bool b_bold, bool b_italic, int i_size, int *i_idx )
{
    FcResult result = FcResultMatch;
    FcPattern *pat, *p_pat;
    FcChar8* val_s;
    FcBool val_b;
    char *ret = NULL;
    FcConfig* config = NULL;
    VLC_UNUSED(p_filter);

    /* Create a pattern and fills it */
    pat = FcPatternCreate();
    if (!pat) return NULL;

    /* */
    FcPatternAddString( pat, FC_FAMILY, (const FcChar8*)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 );
    if( i_size > 0 )
    {
        FcPatternAddDouble( pat, FC_SIZE, (double)i_size );
    }

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

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

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

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

    /* if( strcasecmp((const char*)val_s, family ) != 0 )
        msg_Warn( p_filter, "fontconfig: selected font family is not"
                            "the requested one: '%s' != '%s'\n",
                            (const char*)val_s, family );   */

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

    FcPatternDestroy( p_pat );
    return ret;
}
Beispiel #16
0
int face_from_options(lua_State* L) {
  FT_Face face;
  FcChar8 * font_path, * fullname, * familyname;
  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, "size");
  lua_gettable(L, -2);
  if (lua_isnumber(L, -1)) { pointSize = lua_tonumber(L, -1); }
  lua_pop(L,1);

  lua_pushstring(L, "filename");
  lua_gettable(L, -2);
  if (lua_isstring(L, -1)) {
    font_path = lua_tostring(L, -1);
    lua_pop(L,1);
    lua_newtable(L);
    lua_pushstring(L, "filename");
    lua_pushstring(L, (char*)font_path);
    lua_settable(L, -3);
    goto done_match;
  }
  lua_pop(L,1);

  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, "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, &familyname) != 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*)(familyname));
  lua_settable(L, -3);

  if (FcPatternGetString (matched, FC_FULLNAME, 0, &fullname) == FcResultMatch) {
    lua_pushstring(L, "fullname");
    lua_pushstring(L, (char*)(fullname));
    lua_settable(L, -3);
  }

  FcPatternDestroy (matched);
  FcPatternDestroy (p);

  done_match:
  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;
}
static cairo_status_t
create_scaled_font (cairo_t * cr,
		    cairo_scaled_font_t **out)
{
    FcPattern *pattern, *resolved;
    FcResult result;
    cairo_font_face_t *font_face;
    cairo_scaled_font_t *scaled_font;
    cairo_font_options_t *font_options;
    cairo_matrix_t font_matrix, ctm;
    cairo_status_t status;
    double pixel_size;

    font_options = cairo_font_options_create ();

    cairo_get_font_options (cr, font_options);

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

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

    cairo_ft_font_options_substitute (font_options, pattern);

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

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

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

    font_face = cairo_ft_font_face_create_for_pattern (resolved);

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

    cairo_get_matrix (cr, &ctm);

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

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

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

    *out = scaled_font;
    return CAIRO_STATUS_SUCCESS;
}
Beispiel #18
0
_X_EXPORT FcPattern *
XftXlfdParse (const char *xlfd_orig, FcBool ignore_scalable, FcBool complete)
{
    FcPattern	*pat;
    const char	*xlfd = xlfd_orig;
    const char	*foundry;
    const char	*family;
    const char	*weight_name;
    const char	*slant;
    const char	*registry;
    const char	*encoding;
    char	*save;
    int		pixel;
    int		point;
    int		resx;
    int		resy;
    int		slant_value, weight_value;
    double	dpixel;

    if (*xlfd != '-')
	return NULL;
    if (!(xlfd = strchr (foundry = ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (family = ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (weight_name = ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (slant = ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (/* setwidth_name = */ ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (/* add_style_name = */ ++xlfd, '-'))) return NULL;
    if (!(xlfd = XftGetInt (++xlfd, &pixel))) return NULL;
    if (!(xlfd = XftGetInt (++xlfd, &point))) return NULL;
    if (!(xlfd = XftGetInt (++xlfd, &resx))) return NULL;
    if (!(xlfd = XftGetInt (++xlfd, &resy))) return NULL;
    if (!(xlfd = strchr (/* spacing = */ ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (/* average_width = */ ++xlfd, '-'))) return NULL;
    if (!(xlfd = strchr (registry = ++xlfd, '-'))) return NULL;
    /* make sure no fields follow this one */
    if ((xlfd = strchr (encoding = ++xlfd, '-'))) return NULL;

    if (!pixel)
	return NULL;

    pat = FcPatternCreate ();
    if (!pat)
	return NULL;

    save = (char *) malloc (strlen (foundry) + 1);

    if (!save) {
	FcPatternDestroy (pat);
	return NULL;
    }

    if (!FcPatternAddString (pat, XFT_XLFD, (FcChar8 *) xlfd_orig)) goto bail;

    XftSplitStr (foundry, save);
    if (save[0] && strcmp (save, "*") != 0)
	if (!FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) save)) goto bail;

    XftSplitStr (family, save);
    if (save[0] && strcmp (save, "*") != 0)
	if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) save)) goto bail;

    weight_value = _XftMatchSymbolic (XftXlfdWeights, NUM_XLFD_WEIGHTS,
				      XftSplitStr (weight_name, save),
				      FC_WEIGHT_MEDIUM);
    if (!FcPatternAddInteger (pat, FC_WEIGHT, weight_value))
	goto bail;

    slant_value = _XftMatchSymbolic (XftXlfdSlants, NUM_XLFD_SLANTS,
				     XftSplitStr (slant, save),
				     FC_SLANT_ROMAN);
    if (!FcPatternAddInteger (pat, FC_SLANT, slant_value))
	goto bail;

    dpixel = (double) pixel;

    if (point > 0)
    {
	if (!FcPatternAddDouble (pat, FC_SIZE, ((double) point) / 10.0)) goto bail;
	if (pixel <= 0 && resy > 0)
	{
	    dpixel = (double) point * (double) resy / 720.0;
	}
    }

    if (dpixel > 0)
	if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE, dpixel)) goto bail;

    free (save);
    return pat;

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

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

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

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

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

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

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

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

    FcPatternDestroy(match);
    FcPatternDestroy(pattern);

    return font;
}
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);
}
Beispiel #21
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;
}
Beispiel #22
0
static int parse_font(AVFilterContext *ctx)
{
    DrawTextContext *s = ctx->priv;
#if !CONFIG_LIBFONTCONFIG
    if (!s->fontfile) {
        av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
        return AVERROR(EINVAL);
    }

    return 0;
#else
    FcPattern *pat, *best;
    FcResult result = FcResultMatch;

    FcBool fc_bool;
    FcChar8* fc_string;
    int err = AVERROR(ENOENT);

    if (s->fontfile)
        return 0;

    if (!FcInit())
        return AVERROR_UNKNOWN;

    if (!(pat = FcPatternCreate()))
        return AVERROR(ENOMEM);

    FcPatternAddString(pat, FC_FAMILY, s->font);
    FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
    FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize);

    FcDefaultSubstitute(pat);

    if (!FcConfigSubstitute(NULL, pat, FcMatchPattern)) {
        FcPatternDestroy(pat);
        return AVERROR(ENOMEM);
    }

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

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

    if (FcPatternGetBool(best, FC_OUTLINE, 0, &fc_bool) != FcResultMatch ||
        !fc_bool) {
        av_log(ctx, AV_LOG_ERROR, "Outline not available for %s\n",
               s->font);
        goto fail;
    }

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

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

    s->fontfile = av_strdup(fc_string);
    if (!s->fontfile)
        err = AVERROR(ENOMEM);
    else
        err = 0;

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

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

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

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

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

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

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

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

    return platformData;
}
Beispiel #24
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 */
}
Beispiel #25
0
static Lisp_Object
xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
  FcResult result;
  Display *display = FRAME_X_DISPLAY (f);
  Lisp_Object val, filename, idx, font_object;
  FcPattern *pat = NULL, *match;
  struct xftfont_info *xftfont_info = NULL;
  struct font *font;
  double size = 0;
  XftFont *xftfont = NULL;
  int spacing;
  char name[256];
  int len, i;
  XGlyphInfo extents;
  FT_Face ft_face;
  FcMatrix *matrix;

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

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

  xftfont_add_rendering_parameters (pat, entity);

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


  block_input ();
  /* Make sure that the Xrender extension is added before the Xft one.
     Otherwise, the close-display hook set by Xft is called after the
     one for Xrender, and the former tries to re-add the latter.  This
     results in inconsistency of internal states and leads to X
     protocol error when one reconnects to the same X server.
     (Bug#1696)  */
  {
    int event_base, error_base;
    XRenderQueryExtension (display, &event_base, &error_base);
  }

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

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

  /* We should not destroy PAT here because it is kept in XFTFONT and
     destroyed automatically when XFTFONT is closed.  */
  font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
  ASET (font_object, FONT_TYPE_INDEX, Qxft);
  len = font_unparse_xlfd (entity, size, name, 256);
  if (len > 0)
    ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
  len = font_unparse_fcname (entity, size, name, 256);
  if (len > 0)
    ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
  else
    ASET (font_object, FONT_FULLNAME_INDEX,
	  AREF (font_object, FONT_NAME_INDEX));
  ASET (font_object, FONT_FILE_INDEX, filename);
  ASET (font_object, FONT_FORMAT_INDEX,
	ftfont_font_format (xftfont->pattern, filename));
  font = XFONT_OBJECT (font_object);
  font->pixel_size = size;
  font->driver = &xftfont_driver;
  font->encoding_charset = font->repertory_charset = -1;

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

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

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

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

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

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

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

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

  return font_object;
}
Beispiel #26
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;
    }