changeset 21460:62bd8e0d3a0f

Open embedded fonts directly from memory. FontConfig 2.4.2 (released yesterday) supports scanning fonts with FcFreeTypeQueryFace without writing them to disk. With earlier FontConfig versions, the old mechanism is used.
author eugeni
date Sun, 03 Dec 2006 18:24:11 +0000
parents 44b94d5d70e5
children 71235c49d6ac
files help/help_mp-en.h libass/ass_font.c libass/ass_font.h libass/ass_fontconfig.c libass/ass_fontconfig.h libass/ass_render.c
diffstat 6 files changed, 69 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/help/help_mp-en.h	Sun Dec 03 18:22:07 2006 +0000
+++ b/help/help_mp-en.h	Sun Dec 03 18:24:11 2006 +0000
@@ -2023,6 +2023,7 @@
 #define MSGTR_LIBASS_FcDirSave "[ass] FcDirSave failed.\n"
 #define MSGTR_LIBASS_FcConfigAppFontAddDirFailed "[ass] FcConfigAppFontAddDir failed\n"
 #define MSGTR_LIBASS_FontconfigDisabledDefaultFontWillBeUsed "[ass] Fontconfig disabled, only default font will be used.\n"
+#define MSGTR_LIBASS_FunctionCallFailed "[ass] %s failed\n"
 
 // ass_render.c
 #define MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined "[ass] Neither PlayResX nor PlayResY defined. Assuming 384x288.\n"
@@ -2044,3 +2045,4 @@
 // ass_font.c
 #define MSGTR_LIBASS_GlyphNotFoundReselectingFont "[ass] Glyph 0x%X not found, reselecting font for (%s, %d, %d)\n"
 #define MSGTR_LIBASS_GlyphNotFound "[ass] Glyph 0x%X not found in font for (%s, %d, %d)\n"
+#define MSGTR_LIBASS_ErrorOpeningMemoryFont "[ass] Error opening memory font: %s\n"
--- a/libass/ass_font.c	Sun Dec 03 18:22:07 2006 +0000
+++ b/libass/ass_font.c	Sun Dec 03 18:24:11 2006 +0000
@@ -52,13 +52,23 @@
 	}
 }
 
-ass_font_t* ass_font_new(FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc)
+static int find_font(ass_library_t* library, char* name)
+{
+	int i;
+	for (i = 0; i < library->num_fontdata; ++i)
+		if (strcasecmp(name, library->fontdata[i].name) == 0)
+			return i;
+	return -1;
+}
+
+ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc)
 {
 	char* path;
 	int index;
 	FT_Face face;
 	int error;
 	ass_font_t* font;
+	int mem_idx;
 
 	font = ass_font_cache_find(desc);
 	if (font)
@@ -66,11 +76,21 @@
 	
 	path = fontconfig_select(fc_priv, desc->family, desc->bold, desc->italic, &index);
 	
+	mem_idx = find_font(library, path);
+	if (mem_idx >= 0) {
+		error = FT_New_Memory_Face(ftlibrary, library->fontdata[mem_idx].data,
+					   library->fontdata[mem_idx].size, 0, &face);
+		if (error) {
+			mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, path);
+			return 0;
+		}
+	} else {
 	error = FT_New_Face(ftlibrary, path, index, &face);
 	if (error) {
 		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index);
 		return 0;
 	}
+	}
 
 	charmap_magic(face);
 	
--- a/libass/ass_font.h	Sun Dec 03 18:22:07 2006 +0000
+++ b/libass/ass_font.h	Sun Dec 03 18:24:11 2006 +0000
@@ -45,7 +45,7 @@
 #endif
 } ass_font_t;
 
-ass_font_t* ass_font_new(FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc);
+ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc);
 void ass_font_set_transform(ass_font_t* font, FT_Matrix* m, FT_Vector* v);
 void ass_font_set_size(ass_font_t* font, int size);
 FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch);
--- a/libass/ass_fontconfig.c	Sun Dec 03 18:22:07 2006 +0000
+++ b/libass/ass_fontconfig.c	Sun Dec 03 18:24:11 2006 +0000
@@ -34,6 +34,7 @@
 
 #ifdef HAVE_FONTCONFIG
 #include <fontconfig/fontconfig.h>
+#include <fontconfig/fcfreetype.h>
 #endif
 
 struct fc_instance_s {
@@ -228,7 +229,7 @@
  * \param data binary font data
  * \param data_size data size
 */ 
-static void process_fontdata(fc_instance_t* priv, ass_library_t* library, int idx)
+static void process_fontdata(fc_instance_t* priv, ass_library_t* library, FT_Library ftlibrary, int idx)
 {
 	char buf[1000];
 	FILE* fp = 0;
@@ -239,7 +240,12 @@
 	const char* data = library->fontdata[idx].data;
 	int data_size = library->fontdata[idx].size;
 	const char* fonts_dir = library->fonts_dir;
+	FT_Face face;
+	FcPattern* pattern;
+	FcFontSet* fset;
+	FcBool res;
 
+#if (FC_VERSION < 20402)
 	if (!fonts_dir)
 		return;
 	rc = stat(fonts_dir, &st);
@@ -267,6 +273,38 @@
 
 	fwrite(data, data_size, 1, fp);
 	fclose(fp);
+
+#else // (FC_VERSION >= 20402)
+
+	rc = FT_New_Memory_Face(ftlibrary, data, data_size, 0, &face);
+	if (rc) {
+		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, name);
+		return;
+	}
+
+	pattern = FcFreeTypeQueryFace(face, name, 0, FcConfigGetBlanks(priv->config));
+	if (!pattern) {
+		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFreeTypeQueryFace");
+		FT_Done_Face(face);
+		return;
+	}
+
+	fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication
+	if (!fset) {
+		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcConfigGetFonts");
+		FT_Done_Face(face);
+		return;
+	}
+
+	res = FcFontSetAdd(fset, pattern);
+	if (!res) {
+		mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFontSetAdd");
+		FT_Done_Face(face);
+		return;
+	}
+
+	FT_Done_Face(face);
+#endif
 }
 
 /**
@@ -276,7 +314,7 @@
  * \param path default font path
  * \return pointer to fontconfig private data
 */ 
-fc_instance_t* fontconfig_init(ass_library_t* library, const char* family, const char* path)
+fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path)
 {
 	int rc;
 	struct stat st;
@@ -294,7 +332,7 @@
 	}
 
 	for (i = 0; i < library->num_fontdata; ++i)
-		process_fontdata(priv, library, i);
+		process_fontdata(priv, library, ftlibrary, i);
 
 	if (FcDirCacheValid((const FcChar8 *)dir) == FcFalse)
 	{
@@ -355,7 +393,7 @@
 	return priv->path_default;
 }
 
-fc_instance_t* fontconfig_init(ass_library_t* library, const char* family, const char* path)
+fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path)
 {
 	fc_instance_t* priv;
 
--- a/libass/ass_fontconfig.h	Sun Dec 03 18:22:07 2006 +0000
+++ b/libass/ass_fontconfig.h	Sun Dec 03 18:24:11 2006 +0000
@@ -27,7 +27,7 @@
 
 typedef struct fc_instance_s fc_instance_t;
 
-fc_instance_t* fontconfig_init(ass_library_t* library, const char* family, const char* path);
+fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path);
 char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index);
 void fontconfig_done(fc_instance_t* priv);
 
--- a/libass/ass_render.c	Sun Dec 03 18:22:07 2006 +0000
+++ b/libass/ass_render.c	Sun Dec 03 18:24:11 2006 +0000
@@ -561,7 +561,7 @@
 	else if (val == 1) val = 110; //italic
 	desc.italic = val;
 
-	render_context.font = ass_font_new(priv->ftlibrary, priv->fontconfig_priv, &desc);
+	render_context.font = ass_font_new(priv->library, priv->ftlibrary, priv->fontconfig_priv, &desc);
 	
 	if (render_context.font)
 		change_font_size(render_context.font_size);
@@ -1928,7 +1928,7 @@
 
 	if (priv->fontconfig_priv)
 		fontconfig_done(priv->fontconfig_priv);
-	priv->fontconfig_priv = fontconfig_init(priv->library, default_family, default_font);
+	priv->fontconfig_priv = fontconfig_init(priv->library, priv->ftlibrary, default_family, default_font);
 
 	return !!priv->fontconfig_priv;
 }