The logic here is pretty complicated. The caller of this function guards
it with "if(info->bm || info->bm_o){", and generally indeed only one of
them is set. But in some cases, both are needed. fix_outline()
definitely dereferences both. This is not necessarily guaranteed, e.g.
on out of memory errors. Add the missing checks.
Grigori Goronzy [Sun, 6 Sep 2015 23:29:27 +0000 (01:29 +0200)]
fontconfig: handle fallback corner cases
If no particular codepoint is requested (codepoint == 0), just return
the first font family. Additionally, handle fontconfig errors, albeit
they're unlikely to happen.
Grigori Goronzy [Wed, 2 Sep 2015 22:04:59 +0000 (00:04 +0200)]
fontselect: fix match_fonts semantics
We don't want to add fonts multiple times, so call match_fonts lazily,
i.e. only after selecting a font with a certain name failed. Since
font matching interacts with glyph coverage checks, add a simple
mechanism to determine whether matching failed because of name or
glyph coverage. Additionally make sure to handle substitutions before
any calls to match_fonts; this only correctly deals with single-name
substitutions, though.
CFRelease(NULL) can crash. While we're still not sure which CoreText API
calls can fail etc. (thanks Apple), this should fix a couple of
theoretically possible crashes.
ass_set_fonts_dir() is supposed to enable all fonts in a specific
directory. The implementation for it was dropped with the commit
introducing the new fontselect code. Some users were relying on it, so
we need it back.
It used to be implemented using a single fontconfig call. But since this
has to work even if fontconfig support is not even compiled, a new
implementation is needed.
This commit adds very simple and low-effort support for it. It loads all
files into memory, and then lets the memory font code do the rest. A
more efficient implementation would be possible, for example by
implementing a new font provider, which serves get_data requests from
open file handles. Anyone who wants to do this is welcome to try, and
this commit is just the minimum to restore the lost feature.
wm4 [Fri, 28 Aug 2015 16:34:36 +0000 (18:34 +0200)]
render_api: fix crash when calling ass_set_fonts() after rendering
The caches may reference data which belongs to the font provider. If the
font selector and the font provider are destroyed, it can leave dangling
pointers in the renderer cache. (At least that's what it looks like.)
For some reason, this didn't even trigger valgrind warnings with the
fontconfig font provider. Possibly the dangling pointers were FT_Face
pointers, and fontconfig might cache these process-wide.
wm4 [Fri, 28 Aug 2015 15:39:08 +0000 (17:39 +0200)]
font: fix broken charmap fallback handling
An earlier commit added this code to avoid adding font faces multiple
times. In this form, it breaks the "Trying all charmaps" fallback case,
which can lead to text being rendered as boxes.
Return the font that is going to contain the missing glyph instead. The
calling code will check again, and run the fallback if necessary.
wm4 [Fri, 28 Aug 2015 12:51:09 +0000 (14:51 +0200)]
ass: make font_provider API private
We were discussing whether this should be public or private. It could be
public, because the API is potentially useful, and is relatively simple.
On the other hand, the API is not necessarily final, and making it
public would prevent us from improving/fixing it.
Make it private for now - making it public later is much easier than
having to break the public API later.
wm4 [Fri, 28 Aug 2015 12:35:41 +0000 (14:35 +0200)]
ass: restore ABI compatibility with older versions (more or less)
While enums normally are ints on most systems, it isn't guaranteed. This
might also make C++ code fail to compile, since C++ doesn't allow
implicit conversion of ints to enums.
If the API user ever passed anything other than 0 or 1, compatibility
will still break, but I guess we have to live with this.
wm4 [Fri, 28 Aug 2015 11:54:33 +0000 (13:54 +0200)]
fontselect: correctly match list of font substitutions
This code prioritized fonts by scanning order, but the scanning order is
essentially arbitrary. This resulted in suboptimal and indeterministic
font selection by family name.
Prefer the order as returned by the substitution callback. This requires
some restructuring. The core algorithm is still exactly the same though;
only the order of comparisons changes.
If the font backend has no subtitution callback, nothing should change.
Oleg Oshmyan [Sun, 2 Aug 2015 21:40:16 +0000 (00:40 +0300)]
Properly skip glyphs for multiple consecutive line breaks
This corrects the calculated width of events that contain \N\N,
which previously included the width of the glyph corresponding
to '\n' (more generally, for n consecutive line breaks, only
the first glyph was skipped and n-1 glyphs were included).
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:
Grigori Goronzy [Sun, 14 Jun 2015 10:34:09 +0000 (12:34 +0200)]
directwrite: add font fallback callback
This uses a faux rendering with a high-level interface of DirectWrite
to determine a suitable fallback. Choices are different from GDI,
but reasonable.
Grigori Goronzy [Sat, 13 Jun 2015 14:29:10 +0000 (16:29 +0200)]
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.
Grigori Goronzy [Fri, 12 Jun 2015 19:14:53 +0000 (21:14 +0200)]
fontselect: fix undefined behavior with calloc
If allocations have the size zero, malloc/calloc implementations
can return a zero-size buffer or NULL. The earlier introduced malloc
checking blows up if an implementation returns NULL. Fix that by only
allocating and checking when it's actually needed.
Also fix a minor problem with iconv deinitialization in an error path.
Grigori Goronzy [Fri, 12 Jun 2015 00:04:43 +0000 (02:04 +0200)]
fontselect: simplify lookup of embedded fonts
Currently, it is not safe to change the embedded fonts
(ass_add_font/ass_clear_fonts) while an ASS_Renderer exists. We can
simplify how embedded fonts are looked up because of that.
At some point, ASS_Library and ASS_Renderer should be merged and we
can then implement a more flexible approach.
Grigori Goronzy [Thu, 11 Jun 2015 19:29:35 +0000 (21:29 +0200)]
fontselect: improved and simplified matching
Sorting the font list is overkill and not very useful. We are
interested in *exact* name matches only; all other font families don't
matter and we'll use another fallback mechanism for glyph fallbacks
(TBD).
Replace the sorting and glyph fallback search with a simple linear
scan. Fonts are first matched against family name first (to allow
further comparison against style attributes) and if that fails,
the fullname is considered.
Stefano Pigozzi [Fri, 13 Dec 2013 07:14:43 +0000 (08:14 +0100)]
fontselect: expose a fontprovider listing API
This allows client code to query libass for the font providers it was compiled
with. It can be useful for clients so that they can show selection interfaces
to their users.
Stefano Pigozzi [Tue, 10 Dec 2013 17:45:54 +0000 (18:45 +0100)]
fontselect: expose a fontprovider selection API
Allow the user of libass to select the font provider from ass_set_fonts. This
API change actually doesn't break client code which was passing `fc=1`; now
the same value will autodetect a usable font provider.
Also add an api to list available font providers as that is useful for client
code to show drop down menus with a font provider to choose from.
Stefano Pigozzi [Mon, 9 Dec 2013 18:09:09 +0000 (19:09 +0100)]
fontselect: use fallback fonts when querying font providers
51f9e80b added a MatchFontsFunc callback which allows to lookup font names
directly on the font provider. This approach broke support for font fallback
which worked only with lookups from libass in-memory font database.
This commit moves the font fallback code in the font lookup function, so that
it is available for all font providers.
Stefano Pigozzi [Fri, 6 Dec 2013 17:36:24 +0000 (18:36 +0100)]
coretext: fix conversion from CFStringRef to utf8 buffer
The code incorrectly assumed that the utf8 characters could always be
represented with only one byte. This commit queries CFStringRef instances for
the actual amount of bytes needed.
Stefano Pigozzi [Thu, 5 Dec 2013 18:07:02 +0000 (19:07 +0100)]
coretext: also lazy load fonts based on Family and PostScript names
Previously, the lazy load of fonts was only using display name. Also use the
other names available through the CoreText API (FamilyName and PostScriptName).
Stefano Pigozzi [Sat, 2 Nov 2013 21:01:37 +0000 (22:01 +0100)]
fontselect: coretext: allow to match fontname using the provider
Not all APIs cache everything the same way that fontconfig does. This allows
to first perform a match based on the font name and then score the matched
fonts using the common code using and in memory database approach.
The benefit is the application doesn't have to load all of the fonts and
query for weight, slant, width, path and fullnames.
I left both code paths inside ass_coretext.c. This allows to test matching
problems and have a term of comparison with the slower implementation.
To activate it one just has to flip the CT_FONTS_EAGER_LOAD define to 1.
Here are some benchmarks with a pretty typical OS X font library of ~600 fonts
and using Libass's test program to load a script with 'Helvetica Neue':
CT_FONTS_EAGER_LOAD=0
0.04s user 0.02s system 79% cpu 0.081 total
CT_FONTS_EAGER_LOAD=1
0.12s user 0.06s system 44% cpu 0.420 total
Stefano Pigozzi [Sat, 2 Nov 2013 11:07:07 +0000 (12:07 +0100)]
fontselect: coretext: allow selection based on PostScript name
Up until now fontselect used the face index to identify which font to load
from a font collection. While this pretty convenient when using something
freetype based like fontconfig, it seems to be somewhat freetype specific.
CoreText uses the PostScript name as the unique identifier of a font. This
commit allows to use that instead of the index to decide which face to open
with FT_New_Face. To use the PostScript name the provider must return a -1
index and the PostScript name.
Stefano Pigozzi [Fri, 1 Nov 2013 14:44:25 +0000 (15:44 +0100)]
fontselect: implement a coretext font provider
Fontconfig is known to be very slow on OS X and Windows, this has to do with
the extremely prohibitive cache times (which are getting even longer with
latest versions of Fontconfig).
This commits starts to address the problem by using CoreText on OS X to load
the font data. The commit uses the simplest possible approach to load all of
the data in memory and then use it to match. This causes a somewhat slow
startup time (around ~400ms on my i7) but it is already better than waiting
*minutes* for Fontconfig to cache the fonts data.
A later commit will improve the speed of the match by using a hybrid approach
that lazy loads in the libass database only the necessary fonts.
Grigori Goronzy [Sun, 4 Sep 2011 13:54:38 +0000 (15:54 +0200)]
Support multiple font family names
Some fonts use localized family names, especially CJK fonts, which
often have English and Japanese or Chinese names. Handle these cases
just like full names.