summaryrefslogtreecommitdiffstats
path: root/libass
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 /libass
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.
Diffstat (limited to 'libass')
-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();