dynamically load fonts packaged with Firefox

RESOLVED FIXED in mozilla32

Status

()

defect
RESOLVED FIXED
5 years ago
3 years ago

People

(Reporter: jtd, Assigned: jfkthame)

Tracking

Trunk
mozilla32
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(5 attachments, 1 obsolete attachment)

Reporter

Description

5 years ago
In a couple different contexts, there appears to be the need to activate fonts packaged with Firefox dynamically.  This is needed for the FFOS simulator, where there's a desire to use the same set of fonts used on FFOS devices.  And for FF Desktop there's a need use the same fonts for UI elements across FF versions.

This isn't terribly hard, it is similar to the way @font-face fonts are activated using the various derived versions of gfxPlatformFontList::MakePlatformFont.  The one difference is that in this case you want to treat these as globally available font families, not ones available on a per-document basis.  There are also implementation issues related to memory use (an activated font will increase the RAM footprint) and how to best lazily activate these (need to avoid spending time enumerating these at startup).
Reporter

Comment 1

5 years ago
I think this probably means porting something like gfxFT2FontList::FindFontsInOmnijar to the other platform font back ends.
Reporter

Comment 2

5 years ago
One more thing to consider for this. It might be nice to spec out a packaging format that would allow for a lightweight initialization of font objects associated with these fonts.  In effect, it would be nice to freeze-dry the family name/weight/width/slope/cmap info into a file that could be used to initialize gfxFontEntry objects associated with each font.  That would obviate the need to load the actual fonts via Freetype to pull out this info.
Assignee

Comment 3

5 years ago
(In reply to John Daggett (:jtd) from comment #0)
> In a couple different contexts, there appears to be the need to activate
> fonts packaged with Firefox dynamically.  This is needed for the FFOS
> simulator, where there's a desire to use the same set of fonts used on FFOS
> devices. 

The simulator is a developer tool rather than an end-user, mass-market product; as such, I think a different set of requirements would apply. (E.g. it would be acceptable for there to be a significant startup cost to loading the desired collection of fonts for this purpose, whereas we don't want to affect standard Firefox startup.)

> And for FF Desktop there's a need use the same fonts for UI
> elements across FF versions.

In FF Desktop, UI elements should use standard platform UI fonts. Firefox on Windows should be a Windows application that conforms to the Windows design conventions for UI elements; similarly for Firefox on OS X, etc.

There have been some examples over the years where major applications have failed to honor these conventions, preferring to favor cross-platform uniformity; they have been universally hated by users.
Reporter

Comment 4

5 years ago
(In reply to Jonathan Kew (:jfkthame) from comment #3)
> In FF Desktop, UI elements should use standard platform UI fonts. Firefox on
> Windows should be a Windows application that conforms to the Windows design
> conventions for UI elements; similarly for Firefox on OS X, etc.
> 
> There have been some examples over the years where major applications have
> failed to honor these conventions, preferring to favor cross-platform
> uniformity; they have been universally hated by users.

I agree with you but right now the UI guys are inserting fonts into the browser bundle and using @font-face rules. If we're going to be using application-activated fonts we should support it efficiently, that's my main concern.
Assignee

Comment 5

5 years ago
(In reply to John Daggett (:jtd) from comment #4)
> (In reply to Jonathan Kew (:jfkthame) from comment #3)
> > In FF Desktop, UI elements should use standard platform UI fonts. Firefox on
> > Windows should be a Windows application that conforms to the Windows design
> > conventions for UI elements; similarly for Firefox on OS X, etc.
> > 
> > There have been some examples over the years where major applications have
> > failed to honor these conventions, preferring to favor cross-platform
> > uniformity; they have been universally hated by users.
> 
> I agree with you but right now the UI guys are inserting fonts into the
> browser bundle and using @font-face rules.

And when I run across it I'm commenting that it's the wrong thing to do.

> If we're going to be using
> application-activated fonts we should support it efficiently, that's my main
> concern.

I'm opposed to adding code purely in order to facilitate doing the wrong thing.
In our specific case, I think it's very valuable.

Any step we can do to closer resemble the behavior on the device without the device is saving us a ton of work and bugs, and in particular testing localizations of Firefox OS is very dependent on the right fonts, and is hard to do efficiently on the device.

The Firefox OS guys are working on Mulet (tracked in bug 943878), a project that's Firefox dedicated to testing and developing fx os. We'd be totally fine doing compromises in that app in favor of apps and devices, that won't be a good idea for regular desktop apps.

I've still have to come across an alternative to messing with the fonts the application uses on desktop, really.
Reporter

Comment 7

5 years ago
(In reply to Axel Hecht [:Pike] from comment #6)
> In our specific case, I think it's very valuable.
> 
> Any step we can do to closer resemble the behavior on the device without the
> device is saving us a ton of work and bugs, and in particular testing
> localizations of Firefox OS is very dependent on the right fonts, and is
> hard to do efficiently on the device.

As Jonathan has commented in bug 992210, comment 4, for the B2G Desktop case one alternative is to simply create a package of installable fonts which a user then manually installs on their system.  This would be one more step but it would obviate the need to make code changes just to support this use case.
Blocks: 992210
This blocks bug 948856 because if Firefox OS uses custom fonts to display icons, the simulator will be broken without a cross-platform way to load the icon fonts.

(In reply to John Daggett (:jtd) from comment #7)
> (In reply to Axel Hecht [:Pike] from comment #6)
> > In our specific case, I think it's very valuable.
> > 
> > Any step we can do to closer resemble the behavior on the device without the
> > device is saving us a ton of work and bugs, and in particular testing
> > localizations of Firefox OS is very dependent on the right fonts, and is
> > hard to do efficiently on the device.
> 
> As Jonathan has commented in bug 992210, comment 4, for the B2G Desktop case
> one alternative is to simply create a package of installable fonts which a
> user then manually installs on their system.  This would be one more step
> but it would obviate the need to make code changes just to support this use
> case.

Manual testing of localization in Firefox OS isn't the only use case of a cross-platform way to load fonts. There is the aforementioned issue of icon fonts in Firefox OS; enabling some Firefox OS font-related tests on desktop environments; and it would be great to not require an additional step to make the simulator look exactly like a device, for app developers' sake.

Additionally, I believe this would be beneficial to users in general, because it would allow them to install new fonts without requiring system privileges. I'd like to see addons install new fonts and change font prefs, for specific locales that require special fonts, or for general customization of the browser.

This is already possible on Android and Firefox OS, where font files in the "font" sub-dir of a profile are loaded on startup: http://dxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFT2FontList.cpp#1266

John, do you think it makes sense to do the same on the other platforms?
Blocks: 948856
Flags: needinfo?(jdaggett)
Assignee

Comment 9

5 years ago
(In reply to Axel Hecht [:Pike] from comment #6)

> The Firefox OS guys are working on Mulet (tracked in bug 943878), a project
> that's Firefox dedicated to testing and developing fx os. We'd be totally
> fine doing compromises in that app in favor of apps and devices, that won't
> be a good idea for regular desktop apps.

For a separate product that is designed specifically for testing and developing Firefox OS, I think it could make sense to add code that activates a collection of "embedded" fonts during platform startup, so that they become "installed fonts" for the duration of the session, as far as Gecko is concerned. There'll be some (small) startup-time and RAM usage cost to this, but for a special-purpose developer tool, that's unimportant.

(But I do not think we should do this in the standard desktop Firefox product; it would be within #ifdef MOZ_MULET, or whatever mechanism we have for recognizing a Mulet build at compile time.)

There are still some issues that might prove troublesome: I'm not sure what will happen, for example, if we activate an embedded set of Fira Sans fonts at app startup, but the user already had a (perhaps different/incompatible) set of Fira Sans fonts installed in the host OS.
For FirefoxOS we don't need anything lazy or dynamic. At compile time we know that we are compiling for firefoxOS Desktop and so we essentially just need another system font like "serif" or "monospace".

The one special thing we need though is for the font to only be available certified pages, I.e. based on a nsIPrincipal check.
Reporter

Comment 11

5 years ago
(In reply to Jan Keromnes [:janx] from comment #8)
> Manual testing of localization in Firefox OS isn't the only use case of a
> cross-platform way to load fonts. There is the aforementioned issue of icon
> fonts in Firefox OS; enabling some Firefox OS font-related tests on desktop
> environments; and it would be great to not require an additional step to
> make the simulator look exactly like a device, for app developers' sake.

FxOS is really a separate case, we control the fonts we ship.

> Additionally, I believe this would be beneficial to users in general,
> because it would allow them to install new fonts without requiring system
> privileges. I'd like to see addons install new fonts and change font prefs,
> for specific locales that require special fonts, or for general
> customization of the browser.

For desktop platforms, allowing users to add fonts only for use in Firefox is possible but I'm not sure it's worth the effort.  Regardless, it's a much bigger feature than what's being discussed here.

I do think there will be cases where it makes sense to ship fonts that are activated within Firefox. For supporting MathML stretchy characters and Japanese emphasis characters, cases where we can't rely on a platform font being present.  But those are small and very targeted uses. I don't think we should be shipping large numbers of fonts in Desktop Firefox.

> This is already possible on Android and Firefox OS, where font files in the
> "font" sub-dir of a profile are loaded on startup:
> http://dxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFT2FontList.
> cpp#1266
> 
> John, do you think it makes sense to do the same on the other platforms?

It could but the question is really for what purpose.

(In reply to Jonas Sicking (:sicking) from comment #10)
> The one special thing we need though is for the font to only be available
> certified pages, I.e. based on a nsIPrincipal check.

Hmmm, why would we need to make this special restriction? Why shouldn't a font shipped with Firefox be treated just like any other system font?
Flags: needinfo?(jdaggett)
We want our own internal apps to be able to use

font-face: -moz-icon-font;

However we don't want to leak that onto the public web since it's very FirefoxOS specific. I.e. -moz-icon-font (or whatever we decide to call it) won't work Firefox Android, Firefox Desktop, or in any other browser.
Assignee

Comment 13

5 years ago
(In reply to Jonas Sicking (:sicking) from comment #12)
> We want our own internal apps to be able to use
> 
> font-face: -moz-icon-font;
> 
> However we don't want to leak that onto the public web since it's very
> FirefoxOS specific. I.e. -moz-icon-font (or whatever we decide to call it)
> won't work Firefox Android, Firefox Desktop, or in any other browser.

The Gaia icon font use-case is bug 951593; there are patches to make that possible awaiting review in bug 1008458, but I'm not sure I've persuaded Roc yet....
(In reply to John Daggett (:jtd) from comment #11)
> FxOS is really a separate case, we control the fonts we ship.

In the simulator, we don't control the fonts we ship, because there is currently no way to ship fonts with it. We control which fonts firefox will ask the system for, but we can't make sure they're actually there.

I really think we need a better way to "ship" icon fonts (and other firefox os fonts) with the simulator than prompting the user with an annoying "Thank you for installing our simulator! Please also install these fonts wherever makes sense on your system", and I don't think it's worth creating a semi-intelligent font helper for that.

> > Additionally, I believe this would be beneficial to users in general,
> > because it would allow them to install new fonts without requiring system
> > privileges. I'd like to see addons install new fonts and change font prefs,
> > for specific locales that require special fonts, or for general
> > customization of the browser.
> 
> For desktop platforms, allowing users to add fonts only for use in Firefox
> is possible but I'm not sure it's worth the effort.  Regardless, it's a much
> bigger feature than what's being discussed here.

I'm probably missing some obvious problems here, but I don't see why this feature would be so big, especially since it's already present on a few platforms and maybe just needs unification.

In my mind, it's just a simple file system access to see if there is a "fonts" folder in the profile, and if there is, a loop that loads all the fonts in there. I agree that it might make startup slower and use more memory, but I believe that's an acceptable tradeoff for this feature that only affects performance if there actually is a "fonts" folder.

The only remaining work for users to add custom fonts to their firefox is to change the right font prefs for their locale to point to the newly loaded fonts.

> I do think there will be cases where it makes sense to ship fonts that are
> activated within Firefox. For supporting MathML stretchy characters and
> Japanese emphasis characters, cases where we can't rely on a platform font
> being present.  But those are small and very targeted uses. I don't think we
> should be shipping large numbers of fonts in Desktop Firefox.

We should not ship large numbers of fonts by default, but we could definitely release addons addressing all these particular use cases.

> (In reply to Jonas Sicking (:sicking) from comment #10)
> > The one special thing we need though is for the font to only be available
> > certified pages, I.e. based on a nsIPrincipal check.
> 
> Hmmm, why would we need to make this special restriction? Why shouldn't a
> font shipped with Firefox be treated just like any other system font?

I tend to agree with John regarding the desktop simulator (see below).

(In reply to Jonas Sicking (:sicking) from comment #10)
> For FirefoxOS we don't need anything lazy or dynamic. At compile time we
> know that we are compiling for firefoxOS Desktop and so we essentially just
> need another system font like "serif" or "monospace".
> 
> The one special thing we need though is for the font to only be available
> certified pages, I.e. based on a nsIPrincipal check.

I understand the reasons for wanting to restrict this font to certified apps, so that other apps don't come to rely on the presence of the non-standard font and becoming FirefoxOS-specific. In bug 951593 comment 65, Arnau suggests that non-certified apps re-package the open source font with their app if they really want to use it.

In the simulator however, I'm wondering if it's really that big of a problem to expose these restricted fonts to non-certified apps. It would be a significant difference between simulator and actual devices, but it sounds hard to implement, especially for cross-platform desktop environments. Jonas, do you think the availability of Gaia icon fonts to non-certified apps, only in the simulator, would really cause developers to heavily rely on their presence?
Flags: needinfo?(jonas)
Assignee

Comment 15

5 years ago
So there are a bunch of different use cases and issues that are getting discussed here. Let's try to clarify a bit...

1) Fennec/Android: we already support fonts bundled with the application; that's how we provide the default serif and sans-serif fonts that we use for web content. These fonts are loaded at startup just like the device's system fonts, and are available throughout Gecko (but not in the "chrome" that's implemented in Java, FWIW). So there's nothing to do here.

2) FirefoxOS: we ship the fonts we want as part of the base OS, so there's no problem regarding normal fonts for content, etc. The additional issue there is the desire to ship an icon font for Gaia apps that will *not* be exposed to the web, but only available to certified apps. See bug 951593 and bug 1008458 for a "private font" mechanism to support this.

3) Firefox Desktop: there's been some movement towards bundling fonts for use in "in-content" UI pages such as about:accounts and about:preferences; currently, this is being done in a rather ad hoc way using @font-face. I'm pushing back against this (in bug 992650, bug 1007629, bug 1007639, email discussion...) as I think it's a bad idea for several reasons, but let's see where we end up as far as design is concerned. As for the implementation, if we do keep doing this, using @font-face within the browser's CSS is perfectly adequate, provided we use complete (not Western-European subsetted!) fonts.

4.a) Mulet: here, there's a desire to bundle fonts from FirefoxOS with the desktop emulator, so that users don't need to install them separately into their desktop OS in order to see the FxOS fonts in the emulator. @font-face doesn't work for this, because it doesn't insert the fonts into the global font list, and can't be used to replace the CSS generics like serif, sans-serif, monospace. So I think there's a legitimate case for a platform extension here. As it's aimed only at a dev tool, I'm not concerned if it has some (small) impact on startup time; no need for a fancy lazy-font-loading scheme, just activate the bundled fonts during startup. I'm experimenting with a patch to support this.

4.b) Mulet: once we have the ability to bundle the FxOS fonts with Mulet, the Gaia devs will realize that they want the Gaia icon font included in this - but that it should be exposed only to certified apps, for consistency with the real FxOS platform. So we'll end up wanting the private-font mechanism from (2) above in Mulet as well. At least for OS X and Windows, I think that will be a simple extension; it might be tricker on Linux desktop, but if the Gaia icon font ends up exposed to non-certified code there, I think we could live with that anomaly.

4.c) B2G Simulator: I don't really know anything about how this gets built, so I haven't tried to experiment with it directly, but I assume it'll basically want the same things as Mulet.
The reason we want to limit the -moz-icon-font to certified apps also in B2G Desktop is that we expect a lot of 3rd party developers to be using B2G Desktop and it'll be frustrating for them to create apps that "work" there, but then don't work when testing on the device.

Note that B2G Desktop is a special build and is compiled with MOZ_B2G set at compile time. So no need for anything dynamic here either. I had hoped that we'd be able to use the exact same code for -moz-icon-font on B2G Desktop as on-device.

Is that not possible?
Flags: needinfo?(jonas)
Assignee

Comment 17

5 years ago
(In reply to Jonas Sicking (:sicking) from comment #16)
> The reason we want to limit the -moz-icon-font to certified apps also in B2G
> Desktop is that we expect a lot of 3rd party developers to be using B2G
> Desktop and it'll be frustrating for them to create apps that "work" there,
> but then don't work when testing on the device.
> 
> Note that B2G Desktop is a special build and is compiled with MOZ_B2G set at
> compile time. So no need for anything dynamic here either. I had hoped that
> we'd be able to use the exact same code for -moz-icon-font on B2G Desktop as
> on-device.
> 
> Is that not possible?

The whole process of managing the font list, instantiating fonts in order to render them, etc., is very platform-specific. On desktop platforms, we don't build our main font list by iterating over files in a directory; we query the OS font manager for its available fonts. And we don't render glyphs by handing a font file to Freetype and getting back bitmaps, we do it by instantiating a (platform-specific) font object and asking the OS graphics system to draw them - which means any "private" font we add needs to be registered with the OS font system before we can use it (but not in a way that exposes it more widely).

So no, at a low level in gfx it won't be the same code; but we should be able to implement equivalent behavior to expose to the rest of gecko.
Assignee

Comment 18

5 years ago
Here's a patch that allows us to support "bundled" fonts (any font files found in a /fonts/ folder within the GRE directory) in on desktop systems when building with MOZ_B2G. In my testing, this appears to work OK on all of Windows (GDI and DirectWrite), Mac OS X, and Linux (fontconfig). The patch aims to avoid having any adverse impact on standard Firefox builds; for B2G desktop builds there may be a (slight) startup cost while the GRE/fonts directory is scanned and the fonts activated, but unless someone puts an excessively large number of fonts in there, it shouldn't be an issue.
Attachment #8423117 - Flags: review?(jdaggett)
Excellent, thanks a lot for this! Just tried it on Linux B2G simulator (with the last prefs patch from bug 993137) and it works beautifully.

Out of curiosity, why did you choose to place the "fonts/" folder in the GRE directory and not in the profile directory?
Flags: needinfo?(jfkthame)
Assignee

Comment 20

5 years ago
(In reply to Jan Keromnes [:janx] from comment #19)
> Excellent, thanks a lot for this! Just tried it on Linux B2G simulator (with
> the last prefs patch from bug 993137) and it works beautifully.
> 
> Out of curiosity, why did you choose to place the "fonts/" folder in the GRE
> directory and not in the profile directory?

It seemed to me that for the B2G Desktop "products", the bundled fonts are intended to be a standard part of the product rather than associated with a particular profile. (And if a developer works with multiple profiles, we shouldn't need to duplicate the fonts into all of them.)

But of course this could be reconsidered if it seems wrong.
Flags: needinfo?(jfkthame)
Blocks: 1011562
Reporter

Comment 21

5 years ago
Jonathan, I think this basically looks fine but could I ask you to split the patch into two parts? For the DirectWrite case, I think Bas would be a better person to review the BundledFontFileEnumerator/BundledFontLoader parts, as I don't really trust my knowledge of Windows-isms for these parts.

+// Determine whether desktop platforms should support "bundled" fonts
+// (i.e. load fonts found in a 'fonts' folder within the GRE directory).
+// We want this for Mulet / B2G simulator builds, but not for standard
+// desktop Firefox builds.
+#ifdef MOZ_B2G
+# define MOZ_SUPPORT_BUNDLED_FONTS
+#else
+# undef MOZ_SUPPORT_BUNDLED_FONTS
+#endif

Seems like it would be nice to have this logic in configure.in instead so it can be used by those experimenting with other packaging options.
Assignee

Updated

5 years ago
Assignee: jdaggett → jfkthame
Status: NEW → ASSIGNED
Assignee

Comment 27

5 years ago
Comment on attachment 8423117 [details] [diff] [review]
support "bundled" fonts in desktop B2G builds (simulator, Mulet).

(In reply to John Daggett (:jtd) from comment #21)
> Jonathan, I think this basically looks fine but could I ask you to split the
> patch into two parts? For the DirectWrite case, I think Bas would be a
> better person to review the BundledFontFileEnumerator/BundledFontLoader
> parts, as I don't really trust my knowledge of Windows-isms for these parts.
> 
> +// Determine whether desktop platforms should support "bundled" fonts
> +// (i.e. load fonts found in a 'fonts' folder within the GRE directory).
> +// We want this for Mulet / B2G simulator builds, but not for standard
> +// desktop Firefox builds.
> +#ifdef MOZ_B2G
> +# define MOZ_SUPPORT_BUNDLED_FONTS
> +#else
> +# undef MOZ_SUPPORT_BUNDLED_FONTS
> +#endif
> 
> Seems like it would be nice to have this logic in configure.in instead so it
> can be used by those experimenting with other packaging options.

OK, I've split this into a configure option --enable-bundled-fonts, which is set by default in b2g and b2g/dev; and then per-platform patches to implement this on each of the relevant desktop backends.
Attachment #8423117 - Attachment is obsolete: true
Attachment #8423117 - Flags: review?(jdaggett)
Comment on attachment 8427671 [details] [diff] [review]
part 1 - add configure option to support for bundled fonts (enabled on b2g desktop products).

Review of attachment 8427671 [details] [diff] [review]:
-----------------------------------------------------------------

::: b2g/dev/confvars.sh
@@ +7,5 @@
>  MOZ_MULET=1
>  
>  . ${srcdir}/browser/confvars.sh
> +
> +MOZ_BUNDLED_FONTS=1 

Nit: trailing whitespace
Attachment #8427671 - Flags: review?(gps) → review+
Reporter

Updated

5 years ago
Attachment #8427672 - Flags: review?(jdaggett) → review+
Reporter

Updated

5 years ago
Attachment #8427673 - Flags: review?(jdaggett) → review+
Reporter

Updated

5 years ago
Attachment #8427674 - Flags: review?(jdaggett) → review+
Comment on attachment 8427675 [details] [diff] [review]
part 5 - support bundled fonts on Windows/DWrite.

Review of attachment 8427675 [details] [diff] [review]:
-----------------------------------------------------------------

::: gfx/thebes/gfxDWriteFontList.cpp
@@ +1187,5 @@
> +            if (!localizedName.SetLength(nameLen + 1)) {
> +                continue;
> +            }
> +
> +            hr = names->GetString(nameIndex, localizedName.Elements(), 

nit: While you're in here let's fix this one of my whitespace mistakes too :-)

@@ +1790,5 @@
> +#ifdef MOZ_BUNDLED_FONTS
> +
> +#define IMPL_QI_FOR_DWRITE(_interface)                                   \
> +    public:                                                              \
> +        IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) \

You're required to implement IUnknown here.

@@ +1804,5 @@
> +    : public IDWriteFontFileEnumerator
> +{
> +    IMPL_QI_FOR_DWRITE(IDWriteFontFileEnumerator)
> +
> +    NS_INLINE_DECL_REFCOUNTING(BundledFontFileEnumerator)

I'm not sure if this is technically always compatible with MSCOM, but if it works for now it works I suppose :-)
Attachment #8427675 - Flags: review?(bas) → review+
Assignee

Comment 30

5 years ago
(In reply to Bas Schouten (:bas.schouten) from comment #29)

> @@ +1790,5 @@
> > +#ifdef MOZ_BUNDLED_FONTS
> > +
> > +#define IMPL_QI_FOR_DWRITE(_interface)                                   \
> > +    public:                                                              \
> > +        IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) \
> 
> You're required to implement IUnknown here.

Ah, right - fixed. More importantly, it was failing to AddRef the object before returning. So I've fixed that, too.
You need to log in before you can comment on or make changes to this bug.