LCOV - code coverage report
Current view: top level - gfx/thebes - gfxFontInfoLoader.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3 124 2.4 %
Date: 2017-07-14 16:53:18 Functions: 1 34 2.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "gfxFontInfoLoader.h"
       7             : #include "nsCRT.h"
       8             : #include "nsIObserverService.h"
       9             : #include "nsThreadUtils.h"              // for nsRunnable
      10             : #include "gfxPlatformFontList.h"
      11             : 
      12             : using namespace mozilla;
      13             : using services::GetObserverService;
      14             : 
      15             : #define LOG_FONTINIT(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \
      16             :                                LogLevel::Debug, args)
      17             : #define LOG_FONTINIT_ENABLED() MOZ_LOG_TEST( \
      18             :                                    gfxPlatform::GetLog(eGfxLog_fontinit), \
      19             :                                    LogLevel::Debug)
      20             : 
      21             : void
      22           0 : FontInfoData::Load()
      23             : {
      24           0 :     TimeStamp start = TimeStamp::Now();
      25             : 
      26           0 :     uint32_t i, n = mFontFamiliesToLoad.Length();
      27           0 :     mLoadStats.families = n;
      28           0 :     for (i = 0; i < n && !mCanceled; i++) {
      29             :         // font file memory mapping sometimes causes exceptions - bug 1100949
      30             :         MOZ_SEH_TRY {
      31           0 :             LoadFontFamilyData(mFontFamiliesToLoad[i]);
      32             :         } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
      33             :             gfxCriticalError() <<
      34             :                 "Exception occurred reading font data for " <<
      35             :                 NS_ConvertUTF16toUTF8(mFontFamiliesToLoad[i]).get();
      36             :         }
      37             :     }
      38             : 
      39           0 :     mLoadTime = TimeStamp::Now() - start;
      40           0 : }
      41             : 
      42             : class FontInfoLoadCompleteEvent : public Runnable {
      43           0 :     virtual ~FontInfoLoadCompleteEvent() {}
      44             : 
      45             :     NS_DECL_ISUPPORTS_INHERITED
      46             : 
      47           0 :     explicit FontInfoLoadCompleteEvent(FontInfoData* aFontInfo)
      48           0 :       : mozilla::Runnable("FontInfoLoadCompleteEvent")
      49           0 :       , mFontInfo(aFontInfo)
      50           0 :     {}
      51             : 
      52             :     NS_IMETHOD Run() override;
      53             : 
      54             :     RefPtr<FontInfoData> mFontInfo;
      55             : };
      56             : 
      57             : class AsyncFontInfoLoader : public Runnable {
      58           0 :     virtual ~AsyncFontInfoLoader() {}
      59             : 
      60             :     NS_DECL_ISUPPORTS_INHERITED
      61             : 
      62           0 :     explicit AsyncFontInfoLoader(FontInfoData* aFontInfo)
      63           0 :       : mozilla::Runnable("AsyncFontInfoLoader")
      64           0 :       , mFontInfo(aFontInfo)
      65             :     {
      66           0 :         mCompleteEvent = new FontInfoLoadCompleteEvent(aFontInfo);
      67           0 :     }
      68             : 
      69             :     NS_IMETHOD Run() override;
      70             : 
      71             :     RefPtr<FontInfoData> mFontInfo;
      72             :     RefPtr<FontInfoLoadCompleteEvent> mCompleteEvent;
      73             : };
      74             : 
      75             : class ShutdownThreadEvent : public Runnable {
      76           0 :     virtual ~ShutdownThreadEvent() {}
      77             : 
      78             :     NS_DECL_ISUPPORTS_INHERITED
      79             : 
      80           0 :     explicit ShutdownThreadEvent(nsIThread* aThread)
      81           0 :       : mozilla::Runnable("ShutdownThreadEvent")
      82           0 :       , mThread(aThread)
      83             :     {
      84           0 :     }
      85           0 :     NS_IMETHOD Run() override {
      86           0 :         mThread->Shutdown();
      87           0 :         return NS_OK;
      88             :     }
      89             :     nsCOMPtr<nsIThread> mThread;
      90             : };
      91             : 
      92           0 : NS_IMPL_ISUPPORTS_INHERITED0(ShutdownThreadEvent, Runnable);
      93             : 
      94             : // runs on main thread after async font info loading is done
      95             : nsresult
      96           0 : FontInfoLoadCompleteEvent::Run()
      97             : {
      98             :     gfxFontInfoLoader *loader =
      99           0 :         static_cast<gfxFontInfoLoader*>(gfxPlatformFontList::PlatformFontList());
     100             : 
     101           0 :     loader->FinalizeLoader(mFontInfo);
     102             : 
     103           0 :     return NS_OK;
     104             : }
     105             : 
     106           0 : NS_IMPL_ISUPPORTS_INHERITED0(FontInfoLoadCompleteEvent, Runnable);
     107             : 
     108             : // runs on separate thread
     109             : nsresult
     110           0 : AsyncFontInfoLoader::Run()
     111             : {
     112             :     // load platform-specific font info
     113           0 :     mFontInfo->Load();
     114             : 
     115             :     // post a completion event that transfer the data to the fontlist
     116           0 :     NS_DispatchToMainThread(mCompleteEvent);
     117             : 
     118           0 :     return NS_OK;
     119             : }
     120             : 
     121           0 : NS_IMPL_ISUPPORTS_INHERITED0(AsyncFontInfoLoader, Runnable);
     122             : 
     123           0 : NS_IMPL_ISUPPORTS(gfxFontInfoLoader::ShutdownObserver, nsIObserver)
     124             : 
     125             : NS_IMETHODIMP
     126           0 : gfxFontInfoLoader::ShutdownObserver::Observe(nsISupports *aSubject,
     127             :                                              const char *aTopic,
     128             :                                              const char16_t *someData)
     129             : {
     130           0 :     if (!nsCRT::strcmp(aTopic, "quit-application")) {
     131           0 :         mLoader->CancelLoader();
     132             :     } else {
     133           0 :         NS_NOTREACHED("unexpected notification topic");
     134             :     }
     135           0 :     return NS_OK;
     136             : }
     137             : 
     138             : void
     139           0 : gfxFontInfoLoader::StartLoader(uint32_t aDelay, uint32_t aInterval)
     140             : {
     141           0 :     mInterval = aInterval;
     142             : 
     143           0 :     NS_ASSERTION(!mFontInfo,
     144             :                  "fontinfo should be null when starting font loader");
     145             : 
     146             :     // sanity check
     147           0 :     if (mState != stateInitial &&
     148           0 :         mState != stateTimerOff &&
     149           0 :         mState != stateTimerOnDelay) {
     150           0 :         CancelLoader();
     151             :     }
     152             : 
     153             :     // set up timer
     154           0 :     if (!mTimer) {
     155           0 :         mTimer = do_CreateInstance("@mozilla.org/timer;1");
     156           0 :         if (!mTimer) {
     157           0 :             NS_WARNING("Failure to create font info loader timer");
     158           0 :             return;
     159             :         }
     160             :     }
     161             : 
     162           0 :     AddShutdownObserver();
     163             : 
     164             :     // delay? ==> start async thread after a delay
     165           0 :     if (aDelay) {
     166           0 :         mState = stateTimerOnDelay;
     167           0 :         mTimer->InitWithNamedFuncCallback(DelayedStartCallback,
     168             :                                           this,
     169             :                                           aDelay,
     170             :                                           nsITimer::TYPE_ONE_SHOT,
     171           0 :                                           "gfxFontInfoLoader::StartLoader");
     172           0 :         return;
     173             :     }
     174             : 
     175           0 :     mFontInfo = CreateFontInfoData();
     176             : 
     177             :     // initialize
     178           0 :     InitLoader();
     179             : 
     180             :     // start async load
     181           0 :     nsresult rv = NS_NewNamedThread("Font Loader",
     182           0 :                                     getter_AddRefs(mFontLoaderThread),
     183           0 :                                     nullptr);
     184           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     185           0 :         return;
     186             :     }
     187           0 :     mState = stateAsyncLoad;
     188             : 
     189           0 :     nsCOMPtr<nsIRunnable> loadEvent = new AsyncFontInfoLoader(mFontInfo);
     190             : 
     191           0 :     mFontLoaderThread->Dispatch(loadEvent.forget(), NS_DISPATCH_NORMAL);
     192             : 
     193           0 :     if (LOG_FONTINIT_ENABLED()) {
     194           0 :         LOG_FONTINIT(("(fontinit) fontloader started (fontinfo: %p)\n",
     195             :                       mFontInfo.get()));
     196             :     }
     197             : }
     198             : 
     199             : void
     200           0 : gfxFontInfoLoader::FinalizeLoader(FontInfoData *aFontInfo)
     201             : {
     202             :     // Avoid loading data if loader has already been canceled.
     203             :     // This should mean that CancelLoader() ran and the Load
     204             :     // thread has already Shutdown(), and likely before processing
     205             :     // the Shutdown event it handled the load event and sent back
     206             :     // our Completion event, thus we end up here.
     207           0 :     if (mState != stateAsyncLoad || mFontInfo != aFontInfo) {
     208           0 :         return;
     209             :     }
     210             : 
     211           0 :     mLoadTime = mFontInfo->mLoadTime;
     212             : 
     213             :     // try to load all font data immediately
     214           0 :     if (LoadFontInfo()) {
     215           0 :         CancelLoader();
     216           0 :         return;
     217             :     }
     218             : 
     219             :     // not all work completed ==> run load on interval
     220           0 :     mState = stateTimerOnInterval;
     221           0 :     mTimer->InitWithNamedFuncCallback(LoadFontInfoCallback,
     222             :                                       this,
     223             :                                       mInterval,
     224             :                                       nsITimer::TYPE_REPEATING_SLACK,
     225           0 :                                       "gfxFontInfoLoader::FinalizeLoader");
     226             : }
     227             : 
     228             : void
     229           3 : gfxFontInfoLoader::CancelLoader()
     230             : {
     231           3 :     if (mState == stateInitial) {
     232           3 :         return;
     233             :     }
     234           0 :     mState = stateTimerOff;
     235           0 :     if (mTimer) {
     236           0 :         mTimer->Cancel();
     237           0 :         mTimer = nullptr;
     238             :     }
     239           0 :     if (mFontInfo) // null during any initial delay
     240           0 :         mFontInfo->mCanceled = true;
     241           0 :     if (mFontLoaderThread) {
     242           0 :         NS_DispatchToMainThread(new ShutdownThreadEvent(mFontLoaderThread));
     243           0 :         mFontLoaderThread = nullptr;
     244             :     }
     245           0 :     RemoveShutdownObserver();
     246           0 :     CleanupLoader();
     247             : }
     248             : 
     249             : void
     250           0 : gfxFontInfoLoader::LoadFontInfoTimerFire()
     251             : {
     252           0 :     if (mState == stateTimerOnDelay) {
     253           0 :         mState = stateTimerOnInterval;
     254           0 :         mTimer->SetDelay(mInterval);
     255             :     }
     256             : 
     257           0 :     bool done = LoadFontInfo();
     258           0 :     if (done) {
     259           0 :         CancelLoader();
     260             :     }
     261           0 : }
     262             : 
     263           0 : gfxFontInfoLoader::~gfxFontInfoLoader()
     264             : {
     265           0 :     RemoveShutdownObserver();
     266           0 :     MOZ_COUNT_DTOR(gfxFontInfoLoader);
     267           0 : }
     268             : 
     269             : void
     270           0 : gfxFontInfoLoader::AddShutdownObserver()
     271             : {
     272           0 :     if (mObserver) {
     273           0 :         return;
     274             :     }
     275             : 
     276           0 :     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     277           0 :     if (obs) {
     278           0 :         mObserver = new ShutdownObserver(this);
     279           0 :         obs->AddObserver(mObserver, "quit-application", false);
     280             :     }
     281             : }
     282             : 
     283             : void
     284           0 : gfxFontInfoLoader::RemoveShutdownObserver()
     285             : {
     286           0 :     if (mObserver) {
     287           0 :         nsCOMPtr<nsIObserverService> obs = GetObserverService();
     288           0 :         if (obs) {
     289           0 :             obs->RemoveObserver(mObserver, "quit-application");
     290           0 :             mObserver = nullptr;
     291             :         }
     292             :     }
     293           0 : }

Generated by: LCOV version 1.13