Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-16514

Symbian: Avoid collisions of application fonts

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 4.7.2
    • 4.7.2
    • GUI: Font handling
    • None
    • Symbian
    • cfb7c16d738993fc8a594361f4bdf10e24fa754a

    Description

      This fix is a supplement to QTBUG-6611

      Multiple applications, one font server

      Qt's application font handling uses an underlying Symbian API. That Symbian API loads all application fonts into a system wide "font store". That means that all applications can access all currently loaded fonts. There is no separated access to only the own application fonts. Symbians font enumeration API will show all fonts (system fonts and application fonts) in the same way to all processes. And there are no means to find out if a font on the font server is a System font or an application font (probably of another process).

      No duplicate font names allowed

      The collision on the font server happens,if a font is loaded whose typeface name is the same like the typeface name of an already loaded font. The font loading fails.

      Qt enumerates Server fonts at app startup

      When a Qt application starts up, it populates it's QFontDatabase with all fonts that are available on the font server. Since all fonts look like normal system fonts, the Qt application will also potentially have other processes' application fonts in its QFontDatabase. And it even may use the font.

      What can go wrong?

      These issues can lead to a few, in part serious, scenarios. The following examples are about application A which loads an application font and application B which is then launched. Both applications run side-by-side for a while. The applications can seriously affect eachother.

      • Zombie fonts (only on Symbian^3)
        A loads an app font and B uses it (intentionally or not). A exits before B but cannot unload it's application font since it is still in use by B (the font Server does not unlad a font as long as any CFont's are still active, in any process). The unloading fails silently, CWsScreenDevice::RemoveFile() has no return value.
        So, since only A was the owner of the font file handle (returned by CWsScreenDevice::AddFile) for that loaded font, nobody else can unload that font. The font became an unloadable zombie font. If that happens a few times, there will be many loaded fonts, occupying much RAM.
      • Phone reboot (only on Symbian^1 and below)
        Same situation as with Zombie fonts above, only that here, Symbian does not prevent A from unloading the font. B remains with invalid CFont references and when it uses them, will cause the font server to crash and reboot the phone after showing some funky colors on the screen.
        Just to make it clear, that issue can easily be recreated with non-Qt Symbian apps. A or B or both could be pure Symbian apps in this example. But Qt makes it easer to load application fonts (even automatically in a web site), so that the reboot may happen more often than with non-Qt apps. Therefore, I strongly suggest not to release the implemented feature of QTBUG-6611 for Symbian^1 and below, as long as collisions of application fonts are not prevented by Qt.
      • Font spoofing
        Application A loads a very common font such as 'Comic Sans'. B also tries to load 'Comic Sans' and fails. B is programmed to use 'Comic Sans' and since it's QFontDatabase contains A's 'Comic Sans', B will happily use it.
        Now, A loaded it's special version of 'Comic Sans', which may have special offensive? character symbols or simply different metrics which break the layouts in B.
      • Garbled text (only on Symbian^3|PR1 and below)
        Till Symbian^3|PR2, there was no way to access the font tables of fonts on the server. Qt needs those tables. With an evil hack, Qt currently loads the font tables from the file system, but with Symbian^3|PR2, there is a font table API which gives access to the font tables on the server.
        If application B uses A's app font, it cannot load the font tables from the file system (aforementioned hack). Reason is that there is no way to find out the file name/location of a font from the server. Missing font tables lead to garbled text, mainly because the 'cmap' table is missing.

      Why should Qt handle that?

      Qt could easily ignore all these issues and pass the behavior of the Symbain API (with all its undocumented implications) to the client application. Qt could even document these issues and suggest workarounds like using only fonts with very distict typeface names as application fonts (to avoid the collision). But Qt applications on Symbian are often ported from other platforms, and the code does not handle all these Symbian-esque specialties. So, not handling this collision in Qt would break the cross-platform nature of Qt in this chapter.

      What is the solution?

      (The implementation is already happening here). Since typeface names are where fonts collide, the typeface name of a loaded font should be patched. A unique prefix can be added that allows to identify the font as application font. And the prefix can also contain the uid/pid of the application which loaded the font. Since the application font file needs to be copied around in most cases (see QTBUG-6611 for the reasons), the patching is not a big penalty.
      Caveat: Symbian will trim type face names to 24 characters (I have no clue why, the ttf spec does not require that restriction). So, with the added prefix, the allowed typeface name length is about ~21 characters. Very little! many Web fonts have about ~30 characters in their typeface name. As a result, some webpages will not work well with web fonts.

      Merge request

      http://qt.gitorious.org/qt/qt/merge_requests/2551 ... feel free to just review parts of it. Thanks

      Attachments

        Issue Links

          Activity

            People

              portale Alessandro Portale
              portale Alessandro Portale
              Votes:
              2 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: