summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2023-02-08 03:47:20 +0200
committerOleg Oshmyan <chortos@inbox.lv>2024-01-21 17:41:10 +0200
commitb6650bd51b4c471c32dd3977ca9416c0b35f6358 (patch)
tree8bfac133027be4a3e8af66cc7e52d11b21369b91
parent9f21dbe6aeed336632dadd500c98b2ff7eab3cfa (diff)
downloadlibass-b6650bd51b4c471c32dd3977ca9416c0b35f6358.tar.bz2
libass-b6650bd51b4c471c32dd3977ca9416c0b35f6358.tar.xz
directwrite: always read metadata on our own via FreeType
DirectWrite sometimes returns names that differ from GDI's. Instead of trusting it, use our own GDI-compatible code, even if it costs us some extra resources. Conceptually, this reverts commit 4fb7394f7b9b4f4e4f3e2825c5ec5344a69619f2 "directwrite: read metadata from IDWriteFontFace3 if possible": the refactoring is kept, and so is the read of the PostScript name purely for logging purposes in case of error, but we turn back to (re)reading all metadata on our own. In addition to reverting the logic of the IDWriteFontFace3 path, this also makes the CreateFontFromLOGFONT path similarly go via FreeType. This fixes https://github.com/libass/libass/issues/675 and facilitates future improvements to long font name matching (https://github.com/libass/libass/issues/459). To avoid exotic failures, especially font fallback failures, save DirectWrite's WIN32_FAMILY_NAME as our extended_family. get_fallback returns the WIN32_FAMILY_NAME, and it *should* match what we read for the same font via FreeType, but it is not unfathomable that in some exotic cases it might not match or we might not read any family names at all. fontselect consults the extended_family for fallback fonts and for primary fonts that otherwise have no family names. We might actually want to use WWS_FAMILY_NAME (or presumably equivalently, DirectWrite's first-class font family names) as the extended_family to allow better fallback to multi-weight families given tags like \b900, but there are at least two reasons why WIN32_FAMILY_NAME seems better at the moment: * Across all Windows versions and variants, match_fonts is only guaranteed (if even that) to find a font by its WIN32_FAMILY_NAME. For the fallback font to work, we obviously need match_fonts to be able to find it. We could alleviate this by querying DirectWrite for fonts by its first-class family name in addition to the primary GDI-based path. * While WWS_FAMILY_NAME joins, for example, Arial and Arial Bold, which is desirable, it also joins Arial and Arial Narrow, but we do not distinguish between fonts that differ only in width/stretch. Barring additional width-based ordering logic somewhere, this could lead us to choose an inconsistent combination of fallback font faces, e. g. regular Arial for \i0 with Arial Narrow Italic for \i1.
-rw-r--r--libass/ass_directwrite.c17
-rw-r--r--libass/ass_directwrite_info_template.h49
2 files changed, 5 insertions, 61 deletions
diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c
index f8c2a27..a914768 100644
--- a/libass/ass_directwrite.c
+++ b/libass/ass_directwrite.c
@@ -580,23 +580,6 @@ static char *get_fallback(void *priv, ASS_Library *lib,
return family;
}
-static int map_width(enum DWRITE_FONT_STRETCH stretch)
-{
- 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:
- return FONT_WIDTH_NORMAL;
- }
-}
-
#define FONT_TYPE IDWriteFontFace3
#include "ass_directwrite_info_template.h"
#undef FONT_TYPE
diff --git a/libass/ass_directwrite_info_template.h b/libass/ass_directwrite_info_template.h
index b627124..2fc8118 100644
--- a/libass/ass_directwrite_info_template.h
+++ b/libass/ass_directwrite_info_template.h
@@ -11,14 +11,8 @@ static bool NAME(FONT_TYPE)(FONT_TYPE *font,
HRESULT hr;
BOOL exists;
- meta->weight = font->lpVtbl->GetWeight(font);
- meta->width = map_width(font->lpVtbl->GetStretch(font));
-
- DWRITE_FONT_STYLE style = font->lpVtbl->GetStyle(font);
- meta->slant = (style == DWRITE_FONT_STYLE_NORMAL) ? FONT_SLANT_NONE :
- (style == DWRITE_FONT_STYLE_OBLIQUE)? FONT_SLANT_OBLIQUE :
- (style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE;
-
+ // This PostScript name will merely be logged by
+ // ass_face_stream in case it encounters an error
IDWriteLocalizedStrings *psNames;
hr = font->lpVtbl->GetInformationalStrings(font,
DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames, &exists);
@@ -32,29 +26,6 @@ static bool NAME(FONT_TYPE)(FONT_TYPE *font,
return false;
}
- IDWriteLocalizedStrings *fontNames;
- hr = font->lpVtbl->GetInformationalStrings(font,
- DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames, &exists);
- if (FAILED(hr))
- return false;
-
- if (exists) {
- meta->n_fullname = IDWriteLocalizedStrings_GetCount(fontNames);
- meta->fullnames = calloc(meta->n_fullname, sizeof(char *));
- if (!meta->fullnames) {
- IDWriteLocalizedStrings_Release(fontNames);
- return false;
- }
- for (int k = 0; k < meta->n_fullname; k++) {
- meta->fullnames[k] = get_utf8_name(fontNames, k);
- if (!meta->fullnames[k]) {
- IDWriteLocalizedStrings_Release(fontNames);
- return false;
- }
- }
- IDWriteLocalizedStrings_Release(fontNames);
- }
-
IDWriteLocalizedStrings *familyNames;
hr = font->lpVtbl->GetInformationalStrings(font,
DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists);
@@ -68,20 +39,10 @@ static bool NAME(FONT_TYPE)(FONT_TYPE *font,
if (FAILED(hr))
return false;
- meta->n_family = IDWriteLocalizedStrings_GetCount(familyNames);
- meta->families = calloc(meta->n_family, sizeof(char *));
- if (!meta->families) {
- IDWriteLocalizedStrings_Release(familyNames);
- return false;
- }
- for (int k = 0; k < meta->n_family; k++) {
- meta->families[k] = get_utf8_name(familyNames, k);
- if (!meta->families[k]) {
- IDWriteLocalizedStrings_Release(familyNames);
- return false;
- }
- }
+ meta->extended_family = get_utf8_name(familyNames, 0);
IDWriteLocalizedStrings_Release(familyNames);
+ if (!meta->extended_family)
+ return false;
return true;
}