コード例 #1
0
static String getFontFamilyForCharacters(const UChar* characters, size_t numCharacters)
{
    FcCharSet* cset = FcCharSetCreate();

    for (size_t i = 0; i < numCharacters; ++i) {
        if (U16_IS_SURROGATE(characters[i])
         && U16_IS_SURROGATE_LEAD(characters[i])
         && i != numCharacters - 1
         && U16_IS_TRAIL(characters[i + 1])) {
              if (FcCharSetAddChar(cset, U16_GET_SUPPLEMENTARY(characters[i], characters[i+1])) == FcFalse)
                  return String();
          i++;
        } else
              if (FcCharSetAddChar(cset, characters[i]) == FcFalse)
                  return String();

    }

    FcPattern *pattern = FcPatternCreate();

    FcPatternAddCharSet(pattern, FC_CHARSET, cset);

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

    FcResult result;
    FcPattern *match = FcFontMatch(0, pattern, &result);

    FcChar8 *filename;

    if (FcPatternGetString(match, FC_FILE, 0, &filename) != FcResultMatch) {
        FcCharSetDestroy(cset);
        FcPatternDestroy(match);
        FcPatternDestroy(pattern);
        return String();
    }

    FcChar8* family;

    if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) {
        FcCharSetDestroy(cset);
        FcPatternDestroy(match);
        FcPatternDestroy(pattern);
        const char* charFamily = reinterpret_cast<char*>(family);
        return String(charFamily);
    }

    FcPatternDestroy(match);
    FcCharSetDestroy(cset);
    FcPatternDestroy(pattern);

    return String();
}
コード例 #2
0
ファイル: window.c プロジェクト: muennich/sxiv
int win_draw_text(win_t *win, XftDraw *d, const XftColor *color, int x, int y,
                  char *text, int len, int w)
{
	int err, tw = 0;
	char *t, *next;
	uint32_t rune;
	XftFont *f;
	FcCharSet *fccharset;
	XGlyphInfo ext;

	for (t = text; t - text < len; t = next) {
		next = utf8_decode(t, &rune, &err);
		if (XftCharExists(win->env.dpy, font, rune)) {
			f = font;
		} else { /* fallback font */
			fccharset = FcCharSetCreate();
			FcCharSetAddChar(fccharset, rune);
			f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet,
			                fccharset, FC_SCALABLE, FcTypeBool, FcTrue,
			                FC_SIZE, FcTypeDouble, fontsize, NULL);
			FcCharSetDestroy(fccharset);
		}
		XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext);
		tw += ext.xOff;
		if (tw <= w) {
			XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t);
			x += ext.xOff;
		}
		if (f != font)
			XftFontClose(win->env.dpy, f);
	}
	return tw;
}
コード例 #3
0
ファイル: bcresources.C プロジェクト: TravisKraatz/cinelerra
FcPattern* BC_Resources::find_similar_font(FT_ULong char_code, FcPattern *oldfont)
{
	FcPattern *pat, *font;
	FcFontSet *fs;
	FcObjectSet *os;
	FcCharSet *fcs;
	FcChar8 *file;
	double dval;
	int ival;

	// Do not search control codes
	if(char_code < ' ')
		return 0;

	fontconfig_lock.lock("BC_Resources::find_similar_font");
	pat = FcPatternCreate();
	os = FcObjectSetBuild(FC_FILE, FC_CHARSET, FC_SCALABLE, FC_FAMILY,
		FC_SLANT, FC_WEIGHT, FC_WIDTH, (char *)0);

	FcPatternAddBool(pat, FC_SCALABLE, true);
	fcs = FcCharSetCreate();
	if(FcCharSetAddChar(fcs, char_code))
		FcPatternAddCharSet(pat, FC_CHARSET, fcs);
	FcCharSetDestroy(fcs);
	for(int i = 0; i < LEN_FCPROP; i++)
	{
		if(FcPatternGetInteger(oldfont, fc_properties[i], 0, &ival) == FcResultMatch)
			FcPatternAddInteger(pat, fc_properties[i], ival);
	}
	fs = FcFontList(0, pat, os);

	for(int i = LEN_FCPROP - 1; i >= 0 && fs->nfont == 0; i--)
	{
		FcFontSetDestroy(fs);
		FcPatternDel(pat, fc_properties[i]);
		fs = FcFontList(0, pat, os);
	}
	FcPatternDestroy(pat);
	FcObjectSetDestroy(os);

	pat = 0;

	for (int i = 0; i < fs->nfont; i++)
	{
		font = fs->fonts[i];
		if(FcPatternGetCharSet(font, FC_CHARSET, 0, &fcs) == FcResultMatch)
		{
			if(FcCharSetHasChar(fcs, char_code))
			{
				pat =  FcPatternDuplicate(font);
				break;
			}
		}
	}
	FcFontSetDestroy(fs);
	fontconfig_lock.unlock();

	return pat;
}
コード例 #4
0
ファイル: fontconfig.c プロジェクト: jasperla/birdfont
gchar* find_font_with_property (FcConfig* fontconfig, const gchar* characters, const gchar* property) {
	FcPattern* pattern;
	FcCharSet* character_set;
	FcObjectSet* font_properties;
	FcFontSet* fonts;
	FcPattern* font;
	FcChar8* path;
	gchar* result;
	gchar* remaining_characters;
	gunichar character;
	
	if (fontconfig == NULL) {
		g_warning("Font config not loaded.");
		return NULL;
	}
	
	result = NULL;
	pattern = FcPatternCreate ();
	
	character_set = FcCharSetCreate ();
	
	remaining_characters = (gchar*) characters;
	while (TRUE) {
		character = g_utf8_get_char (remaining_characters);
		
		if (character == '\0') {
			break;
		}
		
		FcCharSetAddChar(character_set, character);
				
		remaining_characters = g_utf8_next_char (remaining_characters);
	}

	FcPatternAddCharSet (pattern, FC_CHARSET, character_set);
	FcCharSetDestroy (character_set);
	FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
	
	FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
	font_properties = FcObjectSetBuild (property, NULL);	
	fonts = FcFontList (fontconfig, pattern, font_properties);
	
	if (fonts && fonts->nfont > 0) {
		font = fonts->fonts[0];
		if (FcPatternGetString(font, property, 0, &path) == FcResultMatch) {
			result = g_strdup ((gchar*) path);
		}
	}

	if (fonts) {
		FcFontSetDestroy(fonts);
	}

	if (pattern) {
		FcPatternDestroy(pattern);
	}

	return result;
}
コード例 #5
0
ファイル: FontCacheFreeType.cpp プロジェクト: kcomkar/webkit
FcPattern* createFontConfigPatternForCharacters(const UChar* characters, int length)
{
    FcPattern* pattern = FcPatternCreate();

    FcCharSet* fontConfigCharSet = FcCharSetCreate();
    for (int i = 0; i < length; ++i) {
        if (U16_IS_SURROGATE(characters[i]) && U16_IS_SURROGATE_LEAD(characters[i])
                && i != length - 1 && U16_IS_TRAIL(characters[i + 1])) {
            FcCharSetAddChar(fontConfigCharSet, U16_GET_SUPPLEMENTARY(characters[i], characters[i+1]));
            i++;
        } else
            FcCharSetAddChar(fontConfigCharSet, characters[i]);
    }
    FcPatternAddCharSet(pattern, FC_CHARSET, fontConfigCharSet);
    FcCharSetDestroy(fontConfigCharSet);

    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);
    return pattern;
}
コード例 #6
0
ファイル: fc-lang.c プロジェクト: batman52/dingux-code
static const FcCharSet *
scan (FILE *f, char *file, FcCharSetFreezer *freezer)
{
    FcCharSet	    *c = 0;
    const FcCharSet *n;
    int		    start, end, ucs4;
    char	    line[1024];
    int		    lineno = 0;

    while (get_line (f, line, &lineno))
    {
	if (!strncmp (line, "include", 7))
	{
	    file = strchr (line, ' ');
            if (!file)
                fatal (line, lineno, 
                       "invalid syntax, expected: include filename");
	    while (isspace(*file))
		file++;
	    f = scanopen (file);
	    if (!f)
		fatal (file, 0, "can't open");
	    n = scan (f, file, freezer);
	    fclose (f);
	    return n;
	}
	if (strchr (line, '-'))
	{
	    if (sscanf (line, "%x-%x", &start, &end) != 2)
		fatal (file, lineno, "parse error");
	}
	else
	{
	    if (sscanf (line, "%x", &start) != 1)
		fatal (file, lineno, "parse error");
	    end = start;
	}
	if (!c)
	    c = FcCharSetCreate ();
	for (ucs4 = start; ucs4 <= end; ucs4++)
	{
	    if (!FcCharSetAddChar (c, ucs4))
		fatal (file, lineno, "out of memory");
	}
    }
    n = FcCharSetFreeze (freezer, c);
    FcCharSetDestroy (c);
    return n;
}
コード例 #7
0
ファイル: fc-lang.c プロジェクト: dikerex/theqvd
static FcCharSet *
scan (FILE *f, char *file)
{
    FcCharSet	*c = 0;
    FcCharSet	*n;
    int		start, end, ucs4;
    char	line[1024];
    int		lineno = 0;

    while (get_line (f, line, &lineno))
    {
	if (!strncmp (line, "include", 7))
	{
	    file = strchr (line, ' ');
	    while (*file == ' ')
		file++;
	    end = strlen (file);
	    if (file[end-1] == '\n')
		file[end-1] = '\0';
	    f = fopen (file, "r");
	    if (!f)
		fatal (file, 0, "can't open");
	    c = scan (f, file);
	    fclose (f);
	    return c;
	}
	if (strchr (line, '-'))
	{
	    if (sscanf (line, "%x-%x", &start, &end) != 2)
		fatal (file, lineno, "parse error");
	}
	else
	{
	    if (sscanf (line, "%x", &start) != 1)
		fatal (file, lineno, "parse error");
	    end = start;
	}
	if (!c)
	    c = FcCharSetCreate ();
	for (ucs4 = start; ucs4 <= end; ucs4++)
	{
	    if (!FcCharSetAddChar (c, ucs4))
		fatal (file, lineno, "out of memory");
	}
    }
    n = FcCharSetFreeze (c);
    FcCharSetDestroy (c);
    return n;
}
コード例 #8
0
FcCharSet *
mozilla_decoder_get_charset (PangoFcDecoder *decoder,
                             PangoFcFont    *fcfont)
{
    MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);

    if (priv->charset)
        return priv->charset;

    // First time this has been accessed.  Populate the charset.
    priv->charset = FcCharSetCreate();

    if (!gCharsetManager) {
        CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
    }

    nsCOMPtr<nsIUnicodeEncoder> encoder;
    nsCOMPtr<nsICharRepresentable> represent;

    if (!gCharsetManager)
        goto end;

    gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
    if (!encoder)
        goto end;
    
    encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');

    priv->uEncoder = encoder;

    represent = do_QueryInterface(encoder);
    if (!represent)
        goto end;

    PRUint32 map[UCS2_MAP_LEN];
    memset(map, 0, sizeof(map));

    represent->FillInfo(map);

    for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
        if (IS_REPRESENTABLE(map, i))
            FcCharSetAddChar(priv->charset, i);
    }

 end:
    return priv->charset;
}
コード例 #9
0
ファイル: FontCacheFreeType.cpp プロジェクト: nickooms/webkit
static RefPtr<FcPattern> createFontConfigPatternForCharacters(const UChar* characters, int bufferLength)
{
    RefPtr<FcPattern> pattern = adoptRef(FcPatternCreate());
    FcUniquePtr<FcCharSet> fontConfigCharSet(FcCharSetCreate());

    UTF16UChar32Iterator iterator(characters, bufferLength);
    UChar32 character = iterator.next();
    while (character != iterator.end()) {
        FcCharSetAddChar(fontConfigCharSet.get(), character);
        character = iterator.next();
    }

    FcPatternAddCharSet(pattern.get(), FC_CHARSET, fontConfigCharSet.get());

    FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
    FcConfigSubstitute(nullptr, pattern.get(), FcMatchPattern);
    FcDefaultSubstitute(pattern.get());
    return pattern;
}
コード例 #10
0
FcPattern* createFontConfigPatternForCharacters(const UChar* characters, int bufferLength)
{
    FcPattern* pattern = FcPatternCreate();
    FcCharSet* fontConfigCharSet = FcCharSetCreate();

    UTF16UChar32Iterator iterator(characters, bufferLength);
    UChar32 character = iterator.next();
    while (character != iterator.end()) {
        FcCharSetAddChar(fontConfigCharSet, character);
        character = iterator.next();
    }

    FcPatternAddCharSet(pattern, FC_CHARSET, fontConfigCharSet);
    FcCharSetDestroy(fontConfigCharSet);

    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
    FcConfigSubstitute(0, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);
    return pattern;
}
コード例 #11
0
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
                                                          const UChar* characters,
                                                          int length)
{
    FcCharSet* cset = FcCharSetCreate();
    for (int i = 0; i < length; ++i)
        FcCharSetAddChar(cset, characters[i]);

    FcPattern* pattern = FcPatternCreate();

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

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

    FcResult result;
    FcPattern* match = FcFontMatch(0, pattern, &result);
    FcPatternDestroy(pattern);

    SimpleFontData* ret = 0;

    if (match) {
        FcChar8* family;
        if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) {
            AtomicString fontFamily(reinterpret_cast<char*>(family));
            ret = getCachedFontData(getCachedFontPlatformData(font.fontDescription(), fontFamily, false));
        }
        FcPatternDestroy(match);
    }

    FcCharSetDestroy(cset);

    return ret;
}
コード例 #12
0
ファイル: drw.c プロジェクト: ffflorian/dwm
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text)
{
	char buf[1024];
	int tx, ty, th;
	Extnts tex;
	XftDraw *d = NULL;
	Fnt *curfont, *nextfont;
	size_t i, len;
	int utf8strlen, utf8charlen, render;
	long utf8codepoint = 0;
	const char *utf8str;
	FcCharSet *fccharset;
	FcPattern *fcpattern;
	FcPattern *match;
	XftResult result;
	int charexists = 0;

	if (!drw->scheme || !drw->fontcount)
		return 0;

	if (!(render = x || y || w || h)) {
		w = ~w;
	} else {
		XSetForeground(drw->dpy, drw->gc, drw->scheme->bg->pix);
		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
		d = XftDrawCreate(drw->dpy, drw->drawable,
		                  DefaultVisual(drw->dpy, drw->screen),
		                  DefaultColormap(drw->dpy, drw->screen));
	}

	curfont = drw->fonts[0];
	while (1) {
		utf8strlen = 0;
		utf8str = text;
		nextfont = NULL;
		while (*text) {
			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
			for (i = 0; i < drw->fontcount; i++) {
				charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
				if (charexists) {
					if (drw->fonts[i] == curfont) {
						utf8strlen += utf8charlen;
						text += utf8charlen;
					} else {
						nextfont = drw->fonts[i];
					}
					break;
				}
			}

			if (!charexists || (nextfont && nextfont != curfont))
				break;
			else
				charexists = 0;
		}

		if (utf8strlen) {
			drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
			/* shorten text if necessary */
			for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
				drw_font_getexts(curfont, utf8str, len, &tex);

			if (len) {
				memcpy(buf, utf8str, len);
				buf[len] = '\0';
				if (len < utf8strlen)
					for (i = len; i && i > len - 3; buf[--i] = '.');

				if (render) {
					th = curfont->ascent + curfont->descent;
					ty = y + (h / 2) - (th / 2) + curfont->ascent;
					tx = x + (h / 2);
					XftDrawStringUtf8(d, &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
				}
				x += tex.w;
				w -= tex.w;
			}
		}

		if (!*text) {
			break;
		} else if (nextfont) {
			charexists = 0;
			curfont = nextfont;
		} else {
			/* Regardless of whether or not a fallback font is found, the
			 * character must be drawn.
			 */
			charexists = 1;

			if (drw->fontcount >= DRW_FONT_CACHE_SIZE)
				continue;

			fccharset = FcCharSetCreate();
			FcCharSetAddChar(fccharset, utf8codepoint);

			if (!drw->fonts[0]->pattern) {
				/* Refer to the comment in drw_font_xcreate for more
				 * information. */
				die("the first font in the cache must be loaded from a font string.\n");
			}

			fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);

			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
			FcDefaultSubstitute(fcpattern);
			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);

			FcCharSetDestroy(fccharset);
			FcPatternDestroy(fcpattern);

			if (match) {
				curfont = drw_font_xcreate(drw, NULL, match);
				if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
					drw->fonts[drw->fontcount++] = curfont;
				} else {
					drw_font_free(curfont);
					curfont = drw->fonts[0];
				}
			}
		}
	}
	if (d)
		XftDrawDestroy(d);

	return x;
}
コード例 #13
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);
}
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;
}
コード例 #15
0
ファイル: gui.c プロジェクト: chinese-opendesktop/oxim
static XftFont *gui_find_font(winlist_t *win, FcChar32 ucs4)
{
    unsigned int i;
    int weight, slant, scalable;
    double font_size;
    FcFontSet *fontset;
    XftFont *font = NULL;

    /* 缺字列表有這個字,那就不用再找啦 */
    if (FcCharSetHasChar(gui->missing_chars, ucs4))
    {
	return NULL;
    }

    /* 找出 Cache 相符的字型 */
    for (i=0 ; i < gui->num_fonts ; i++)
    {
	XftPatternGetDouble(gui->xftfonts[i]->pattern, XFT_PIXEL_SIZE, 0, &font_size);
	if ((int)font_size == win->font_size &&
	    FcCharSetHasChar(gui->xftfonts[i]->charset, ucs4))
	{
	    return gui->xftfonts[i];
	}
    }

    /* 列出所有可能的字型 */
    FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_CHARSET, NULL);
    /* 只要標準、非斜體、可縮放字型即可 */
    FcPattern *listpat = FcPatternBuild(NULL,
				FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN,
				FC_SCALABLE, FcTypeBool, FcTrue,
				NULL);
    fontset = FcFontList(NULL, listpat, os);
    FcPatternDestroy(listpat);
    FcObjectSetDestroy(os);

    for (i=0; i< fontset->nfont; i++)
    {
	FcPattern *pat = fontset->fonts[i];
	FcCharSet *fcs = NULL;

	if (FcPatternGetCharSet(pat, FC_CHARSET, 0, &fcs) != FcResultMatch)
	    continue;

	if (!FcCharSetHasChar(fcs, ucs4))
	    continue;

	FcResult res;
	FcPattern *mpat = FcFontMatch(0, pat, &res);
	if (!mpat)
	    continue;

	XftPatternAddDouble(mpat, XFT_PIXEL_SIZE, (double)win->font_size);
	XftFont *chkfont = XftFontOpenPattern(gui->display, mpat);

        if (chkfont)
	{
	    gui->num_fonts ++;
	    gui->xftfonts = (XftFont **)oxim_realloc(gui->xftfonts, gui->num_fonts * sizeof(XftFont *));
	    if (!gui->xftfonts)
	    {
		FcPatternDestroy(mpat);
		continue;
	    }
	    gui->xftfonts[gui->num_fonts - 1] = chkfont;
	    font = chkfont;
	    break;
	}
	else
	{
	    FcPatternDestroy(mpat);
	}
    }

    FcFontSetDestroy(fontset);

    if (!font)
	FcCharSetAddChar(gui->missing_chars, ucs4);

    return font;
}