summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2015-06-13 16:29:10 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:43:16 +0200
commit4f206a3fbe6150ce9d547952db7b93a884e024ab (patch)
treeb05b1c000b0267768a2b9dfa90c34098a863a5f2
parent832d57bf22426982bce1ffbf69121afb887b1cb6 (diff)
downloadlibass-4f206a3fbe6150ce9d547952db7b93a884e024ab.tar.bz2
libass-4f206a3fbe6150ce9d547952db7b93a884e024ab.tar.xz
directwrite: multiple improvements to font scanning
There were various issues with font scanning. This addresses the following: - Synthesized font faces (bold/oblique) were added to the list. Just skip those, this is handled internally by libass. - Use the win32 font family names, if available. Traditionally, Windows groups font families in a different way, so that the number of variants is small (<= 4). With this, Arial Narrow and Arial Black appear as a separate family, which is what we want. - Full names are not mandatory. Correctly handle the case that there are no full names. - Don't use the bogus LOCALE_NAME_MAX_LENGTH constant to determine the size of the name buffer. Names can be almost arbitrarily long. Handle names up to 256 characters correctly and truncate longer names.
-rw-r--r--libass/ass_directwrite.cpp81
1 files changed, 52 insertions, 29 deletions
diff --git a/libass/ass_directwrite.cpp b/libass/ass_directwrite.cpp
index f8feecf..9bc8ce9 100644
--- a/libass/ass_directwrite.cpp
+++ b/libass/ass_directwrite.cpp
@@ -27,6 +27,8 @@ extern "C" {
#include "ass_utils.h"
}
+#define NAME_MAX_LENGTH 256
+
/*
* The private data stored for every font, detected by this backend.
*/
@@ -177,9 +179,21 @@ static void destroy_font(void *data)
free(priv);
}
-static int map_width(int stretch)
+static int map_width(enum DWRITE_FONT_STRETCH stretch)
{
- return stretch * (100 / DWRITE_FONT_STRETCH_MEDIUM);
+ switch (stretch) {
+ case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: return 50;
+ case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: return 63;
+ case DWRITE_FONT_STRETCH_CONDENSED: return FONT_WIDTH_CONDENSED;
+ case DWRITE_FONT_STRETCH_SEMI_CONDENSED: return 88;
+ case DWRITE_FONT_STRETCH_MEDIUM: return FONT_WIDTH_NORMAL;
+ case DWRITE_FONT_STRETCH_SEMI_EXPANDED: return 113;
+ case DWRITE_FONT_STRETCH_EXPANDED: return FONT_WIDTH_EXPANDED;
+ case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: return 150;
+ case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: return 200;
+ default:
+ assert(0);
+ }
}
/*
@@ -197,7 +211,7 @@ static void scan_fonts(IDWriteFactory *factory,
DWRITE_FONT_STYLE style;
ASS_FontProviderMetaData meta = ASS_FontProviderMetaData();
hr = factory->GetSystemFontCollection(&fontCollection, FALSE);
- wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
+ wchar_t temp_name[NAME_MAX_LENGTH];
int size_needed = 0;
if (FAILED(hr) || !fontCollection)
@@ -215,7 +229,7 @@ static void scan_fonts(IDWriteFactory *factory,
hr = fontCollection->GetFontFamily(i, &fontFamily);
if (FAILED(hr))
- return;
+ continue;
UINT32 fontCount = fontFamily->GetFontCount();
for (UINT32 j = 0; j < fontCount; ++j) {
@@ -223,6 +237,13 @@ static void scan_fonts(IDWriteFactory *factory,
if (FAILED(hr))
continue;
+ // Simulations for bold or oblique are sometimes synthesized by
+ // DirectWrite. We are only interested in physical fonts.
+ if (font->GetSimulations() != 0) {
+ font->Release();
+ continue;
+ }
+
meta.weight = font->GetWeight();
meta.width = map_width(font->GetStretch());
font->GetMetrics(&metrics);
@@ -232,68 +253,70 @@ static void scan_fonts(IDWriteFactory *factory,
(style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE;
hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames,&exists);
-
if (FAILED(hr)) {
font->Release();
continue;
}
if (exists) {
- hr = psNames->GetString(0, localeName, LOCALE_NAME_MAX_LENGTH + 1);
+ hr = psNames->GetString(0, temp_name, NAME_MAX_LENGTH);
if (FAILED(hr)) {
psNames->Release();
font->Release();
continue;
}
- size_needed = WideCharToMultiByte(CP_UTF8, 0, localeName, -1, NULL, 0,NULL, NULL);
+ temp_name[NAME_MAX_LENGTH-1] = 0;
+ size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL);
psName = (char *) malloc(size_needed);
- WideCharToMultiByte(CP_UTF8, 0, localeName, -1, psName,size_needed, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, psName, size_needed, NULL, NULL);
+ psNames->Release();
}
- psNames->Release();
-
hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames,&exists);
if (FAILED(hr)) {
font->Release();
continue;
}
- meta.n_fullname = fontNames->GetCount();
- meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *));
- for (UINT32 k = 0; k < meta.n_fullname; ++k) {
- hr = fontNames->GetString(k, localeName,LOCALE_NAME_MAX_LENGTH + 1);
-
- if (FAILED(hr)) {
- continue;
+ if (exists) {
+ meta.n_fullname = fontNames->GetCount();
+ meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *));
+ for (UINT32 k = 0; k < meta.n_fullname; ++k) {
+ hr = fontNames->GetString(k, temp_name, NAME_MAX_LENGTH);
+ if (FAILED(hr)) {
+ continue;
+ }
+
+ temp_name[NAME_MAX_LENGTH-1] = 0;
+ size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL);
+ char *mbName = (char *) malloc(size_needed);
+ WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL);
+ meta.fullnames[k] = mbName;
}
-
- size_needed = WideCharToMultiByte(CP_UTF8, 0, localeName, -1, NULL, 0, NULL, NULL);
- char *mbName = (char *) malloc(size_needed);
- WideCharToMultiByte(CP_UTF8, 0, localeName, -1, mbName,size_needed, NULL, NULL);
- meta.fullnames[k] = mbName;
+ fontNames->Release();
}
- fontNames->Release();
- hr = fontFamily->GetFamilyNames(&familyNames);
+ hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists);
+ if (!exists)
+ hr = fontFamily->GetFamilyNames(&familyNames);
if (FAILED(hr)) {
font->Release();
continue;
}
-
meta.n_family = familyNames->GetCount();
meta.families = (char **) calloc(meta.n_family, sizeof(char *));
for (UINT32 k = 0; k < meta.n_family; ++k) {
- hr = familyNames->GetString(k, localeName, LOCALE_NAME_MAX_LENGTH + 1);
-
+ hr = familyNames->GetString(k, temp_name, NAME_MAX_LENGTH);
if (FAILED(hr)) {
continue;
}
- size_needed = WideCharToMultiByte(CP_UTF8, 0, localeName, -1, NULL, 0,NULL, NULL);
+ temp_name[NAME_MAX_LENGTH-1] = 0;
+ size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL);
char *mbName = (char *) malloc(size_needed);
- WideCharToMultiByte(CP_UTF8, 0, localeName, -1, mbName,size_needed, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL);
meta.families[k] = mbName;
}
familyNames->Release();