summaryrefslogtreecommitdiffstats
path: root/libass/ass_directwrite.c
Commit message (Collapse)AuthorAgeFilesLines
* directwrite: verify font name case-insensitivelyOleg Oshmyan2024-04-091-1/+1
| | | | | | | | | | | | | | | | GDI uses case-insensitive matching. We now request the font's full name, but if it case-insensitively matches the family name, GDI decides that it's a family-name match and returns the family name from GetTextFace instead of the full name we originally requested, which then fails our case-sensitive equality check. An actual example of an affected font is Microsoft YaHei UI (Regular). Its family name is spelt "YaHei" in the name table records marked English and Chinese, but its full name is actually spelt "YaHei" in the English record but "Yahei" in the Chinese one. Thus, on Chinese locales only, requesting "Microsoft YaHei UI" gets "Microsoft Yahei UI" back, fails the check and discards the font, causing the bold version to be used instead, as reported in https://github.com/mpv-player/mpv/issues/13845.
* directwrite: query GDI-enumerated fonts by full name, not family nameOleg Oshmyan2024-04-081-2/+16
| | | | Fixes: https://github.com/libass/libass/issues/744
* directwrite: fix outdated dealloc code that has become leakyOleg Oshmyan2024-02-191-24/+2
| | | | | | | | | Regression in commit b6650bd51b4c471c32dd3977ca9416c0b35f6358: fullnames and families are no longer allocated, so freeing them is pointless, wherease extended_family is allocated in their stead and yet is never freed. Reported-by: @moi15moi
* directwrite: try to fill extended_family even without IDWriteFontFace3Oleg Oshmyan2024-01-211-9/+30
|
* directwrite: add a backup source of name for fallback fontOleg Oshmyan2024-01-211-1/+9
| | | | | | | | | | I don't know if it is actually _possible_ in practice for DirectWrite to return zero WIN32_FAMILY_NAMES for a font, but we do currently guard against this in ass_directwrite_info_template.h. Use the same logic here. This name seems somewhat likely to fail to be found by match_fonts depending on the exact font and version of the Windows environment, but this is still better than not even trying.
* directwrite: always read metadata on our own via FreeTypeOleg Oshmyan2024-01-211-17/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* refactor: do not cast allocationsOneric2022-01-201-5/+5
|
* directwrite: read metadata from IDWriteFontFace3 if possibleOleg Oshmyan2021-07-101-75/+47
| | | | This avoids an extra trip to FreeType.
* directwrite: better match_fonts via GDI or IDWriteFontSetOleg Oshmyan2021-07-101-34/+358
| | | | | | | | | | | | | | | | | | | | | | | | | | CreateFontFromLOGFONT does not actually use GDI's font lookup logic and fails to emulate it faithfully. In particular: it fails to find CFF-outline fonts by PostScript name; it fails to find TrueType fonts by full name on older versions of Windows; it fails to find at least some fonts installed on demand by font managers. When GDI is available, invoke GDI directly. This commit uses EnumFontFamilies, which is almost perfect, except that if the user has two different fonts such that one font's family name equals another's full/PostScript name, this will find only the family name match. To fix this case as well, we'd need to invoke CreateFontIndirect separately for each font request, complete with its weight and slant. This requires larger changes in our fontselect, which this commit does not attempt yet. GDI is not available in WinRT/UWP. On UWP (Windows 10), use the new IDWriteFontSet API to emulate GDI's font lookup as well as we can. In WinRT (Windows 8), we have no choice but to keep using CreateFontFromLOGFONT (unless we go back to loading all fonts eagerly, which we stopped doing for performance reasons). It is the builder's responsibility to avoid linking in Gdi32.lib in WinRT/UWP builds, just as it is to link in Dwrite.lib.
* directwrite: support WinRT/UWP, which forbid LoadLibraryOleg Oshmyan2021-07-101-7/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | Normally, we delay loading Dwrite.dll until runtime to allow building and running DirectWrite-enabled libass binaries on old Windows versions that lack DirectWrite. However, this is forbidden in WinRT/UWP. DirectWrite is present in all versions of Windows that support WinRT/UWP, so we lose nothing by requiring it. Older Windows SDKs (Microsoft and MinGW alike) lack <winapifamily.h>, so include it only if we really need it. Based on VLC patch for libass: https://github.com/videolan/vlc/commit/eedb57aa96d2bc0046a6da2e081c75ae9edf8fd5 and on this autoconf code: https://github.com/lu-zero/mfx_dispatch/commit/c51a54c15f51579804030c70592c0a26065f1242 Note: the VLC patch retained an unconditional call to FreeLibrary in destroy_provider. However, FreeLibrary does not actually expect NULL as argument, so this commit adds a guard to that call. Perhaps FreeLibrary(NULL) simply fails cleanly and that's why this has not caused VLC problems, but we should not rely on this.
* directwrite: remove unused #includesOleg Oshmyan2021-07-101-2/+0
|
* directwrite: remove arbitrary 256-char name length limitOleg Oshmyan2021-07-101-10/+28
|
* directwrite: reorder code to avoid possible unneeded allocationOleg Oshmyan2021-07-101-12/+11
|
* directwrite: factor out conversion to UTF-8Oleg Oshmyan2021-07-101-58/+26
|
* directwrite: don't use wrong family names on errorOleg Oshmyan2021-07-101-1/+1
|
* directwrite: add whole font family from `match_fonts`Apache5532021-05-121-9/+16
| | | | | | | match_fonts is supposed to add all the fonts with the same family name for fontselect. Commit d325c633f4ac32fcb4c76a3fb5926737a45c38d0 adds only one font, which leads to inability to select (using family name) correct fonts from families with multiple styles.
* directwrite: request font on demandApache5532021-05-011-34/+46
| | | | | | | | | | | | scan_fonts can be very slow when many fonts were installed in the system. Use IDWriteGdiInterop to create a font by its name when needed instead of scanning all installed fonts during the initializing stage to get better performance. In case of a non-existent font, the fallback mechanism should do its work. Fixes https://github.com/libass/libass/issues/334. Signed-off-by: Oleg Oshmyan <chortos@inbox.lv>
* directwrite: cast function pointer through void* to quelch warningOleg Oshmyan2021-05-011-2/+3
| | | | | GCC and MSVC (at least) warn about this cast as the function types appear to be incompatible. This is correct with GetProcAddress.
* fontselect: coretext: get fallback font family name via FreeTypeOleg Oshmyan2021-04-291-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since commit be0d1613f79a95073d18d96a60e1394abf9316a2, get_fallback can return a name from Core Text that is different from all names that match_fonts registers for the same font. This causes font fallback to fail as find_fonts fails to find any font having the name received from get_fallback. (Moreover, libass will keep retrying fallback for other glyphs, and the coretext match_fonts will keep readding the same fonts over and over again.) Commit 152d0484e98f118d01987138695cf40579c9e297 attempted to fix font fallback by getting a full name from Core Text instead of a family name when it was noticed that Core Text's family name can come from TT_NAME_ID_TYPOGRAPHIC_FAMILY in addition to TT_NAME_ID_FONT_FAMILY, which we fetch in get_font_info, but the problem goes deeper: Core Text can return Macintosh-platform names that don't match Microsoft-platform names, or the font might have no Microsoft-platform names at all. Furthermore, returning a full name breaks style matching: get_fallback does not know about weight, slant etc. and is expected to return a whole family of fonts that will be lazy-loaded in its entirety (if applicable) and searched through for the best stylistic match by find_fonts. To fix fallback while preserving maximum name portability in the spirit of be0d1613f79a95073d18d96a60e1394abf9316a2, use the same API in get_fallback as is used in match_fonts to look up a family name. Note: this could be more efficient if ass_get_font_info could be told to return just an arbitrary family name. This fixes https://github.com/libass/libass/issues/457.
* fontselect: coretext: reuse main FT_LibraryOleg Oshmyan2021-04-291-1/+2
|
* Style-Nit: Adjust whitespacesOneric2020-07-051-1/+1
| | | | | | | - Convert tabs to spaces - Ensure one space between keywords and parenthesis - Ensure space between ')' and '{' - Trim trailing whitespace
* directwrite: fix font collectionsGrigori Goronzy2017-06-011-0/+14
| | | | | | | | | | | | | | | | DirectWrite's FontFileStream does not actually use the data of a specific font in a collection, which was an expectation of the existing code. It simply returns a stream to the underlying file, collection or not. So we need to get the index of the font. This needs to be done lazily as this information is only available in a FontFace, which is expensive to initialize. Add a new optional font provider function for lazy initialization of the index and use it. This is similar to the check_postscript callback. Fixes libass#275. v2: fix type of returned value.
* directwrite: drop SAL annotationsOleg Oshmyan2016-12-281-16/+16
| | | | | | | MinGW and old versions of mingw-w64 don't define the SAL macros. They don't serve any value to us, so just remove them from our code. See https://github.com/libass/libass/pull/251.
* directwrite: fix leaks of IDWriteFontFamily/IDWriteFontCollectionHannes Domani2016-03-271-0/+4
|
* fontselect: replace is_postscript flag with check_postscript functionOleg Oshmyan2015-11-041-34/+46
| | | | | | | | | | | | | | | | | | | | | | | DirectWrite does not provide fast access to the is_postscript flag, requiring each font to be loaded before its format can be determined. Eagerly doing this for every installed font can be quite slow, on the order of seconds. To improve performance, ask the font provider for this information only when it is actually needed, i.e. when one of the font's full names or its PostScript name matches a requested font name and we need to know whether to accept this match. The return value of check_postscript is not cached in this commit. This makes repeated calls slower than accessing is_postscript was. This should not be a problem, but if it is, the value can be cached (or precomputed) by font providers in their font private data. This commit also potentially increases the memory usage of some font providers by retaining data structures needed to implement check_postscript in their font private data. This should not be a problem either, but if it is, the value of check_postscript can be precomputed by all providers other than DirectWrite.
* directwrite: improve error handlingOleg Oshmyan2015-10-301-23/+51
| | | | | | | | | | * Check malloc and calloc return values. * Abort if a name can't be fetched, rather than supply a NULL string to fontselect causing it to crash. * Make sure to free all allocated memory. * Always check FAILED(hr) before using the value of any output argument returned by DirectWrite, because it is not clear whether they are guaranteed to have correct values in case of error.
* directwrite: slightly clean up the codeOleg Oshmyan2015-10-301-19/+17
| | | | | | | | | * Metrics are not used, so don't fetch them. * All variables except meta are always explicitly set before use, so don't initialize them. * Declare variables where they are used. * Use int loop variables when the loop bound is int. * Prefer post-increment to pre-increment.
* directwrite: split out the inner loop of scan_fonts as a separate functionOleg Oshmyan2015-10-301-109/+117
| | | | | | | | | | | | This has the side effect that the ASS_FontProviderMetaData instance is now cleared for every font rather than only once at the start of the search, which fixes some use-after-free scenarios and prevents the creation of chimeric fonts using names left over from other fonts processed earlier. This lays the groundwork for further code simplification and error handling improvements within this function, which will come in a separate commit. This commit is transparent to `git blame -w` except for return statements.
* fontselect: use stdbool.h wherever appropriateOleg Oshmyan2015-10-231-5/+4
|
* directwrite: fix broken return value checkOleg Oshmyan2015-10-231-1/+1
|
* fontselect: find fonts with PostScript outlines by PostScript nameOleg Oshmyan2015-10-231-0/+20
| | | | | | | Fonts without PostScript outlines (such as TrueType fonts) are unaffected, and their PostScript names continue to be ignored when searching for fonts. This matches the behavior of GDI and hence VSFilter.
* fontselect: move PostScript name into ASS_FontProviderMetaDataOleg Oshmyan2015-10-211-5/+6
|
* Fully fix compilation with MSVC/ICLOleg Oshmyan2015-09-171-0/+1
| | | | | | | | | As before, this does not add any build system support: a config.h file and a project must still be manually created (or the compiler can be run manually instead of using a project). Signed-off-by: Grigori Goronzy <greg@kinoho.net> Signed-off-by: Oleg Oshmyan <chortos@inbox.lv>
* directwrite: change WINBOOL to BOOL.torque2015-09-171-2/+2
| | | | WINBOOL is MingW-specific.
* directwrite: fix syntax error with MSVC.torque2015-09-171-1/+1
| | | | | MSVC requires the calling convention to be grouped with the identifier when defining a callback type.
* directwrite, coretext: implement substitutionsGrigori Goronzy2015-09-021-0/+14
| | | | | This adds simple and sensible substitutions for generic font family names. A helper function is introduced to reduce code duplication.
* directwrite: fix fallback for codepoint 0Grigori Goronzy2015-09-011-5/+7
|
* directwrite: fix compilationGrigori Goronzy2015-09-011-1/+1
| | | | A name clash was introduced by commit ab08d079.
* fontselect: simplify get_fallback signaturewm42015-09-011-2/+1
| | | | | Apparently we only need the font family (and even that isn't used in all font providers). Drop the others.
* fontselect: use designated initializerswm42015-09-011-7/+5
| | | | | | Tired of matching the names and order of the callbacks in my head. While we're at it, also give some of the callbacks better names.
* Rename dwrite.h, minor cleanupswm42015-08-051-5/+1
| | | | | | | Rename dwrite.h to dwrite_c.h to make the difference between the official header and ours clearer. Also apply minor cleanups to it. Remove the patch against upstream MinGW; it's pointless now.
* directwrite: don't crash on unknown DWRITE_FONT_STRETCHwm42015-07-111-1/+1
| | | | | The existing code doesn't even handle all currently defined values for it, and nothing says no new values are ever going to be added.
* directwrite: convert to Cwm42015-07-111-0/+706
Unfortunately, nobody ever tested the MinGW dwrite.h header in C. There are multiple glaring mistakes, and the header doesn't even compile by itself. The main issues are overloaded functions (which doesn't work in C), and broken COBJMACROS defines. dwrite.diff contains changes to dwrite.h which make libass work. Warning: the patch lacks a required change to the DrawInlineObject method of IDWriteTextRenderer (missing THIS_). Additionally, these definitions would ideally be provided by dwrite.h: DEFINE_GUID(IID_IDWriteFactory, 0xb859ee5a,0xd838,0x4b5b,0xa2,0xe8,0x1a,0xdc,0x7d,0x93,0xdb,0x48); DEFINE_GUID(IID_IDWritePixelSnapping, 0xeaf3a2da,0xecf4,0x4d24,0xb6,0x44,0xb3,0x4f,0x68,0x42,0x02,0x4b); DEFINE_GUID(IID_IDWriteTextRenderer, 0xef8a8135,0x5cc6,0x45fe,0x88,0x25,0xc5,0xa0,0x72,0x4e,0xb8,0x19); Also, in order to make libass compile out of the box with current MinGW/msys installations, a very stripped down in-tree copy of dwrite.h is provided.