LCOV - code coverage report
Current view: top level - gfx/src - nsDeviceContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 142 311 45.7 %
Date: 2017-07-14 16:53:18 Functions: 21 44 47.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set sw=4 ts=4 expandtab: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsDeviceContext.h"
       8             : #include <algorithm>                    // for max
       9             : #include "gfxASurface.h"                // for gfxASurface, etc
      10             : #include "gfxContext.h"
      11             : #include "gfxFont.h"                    // for gfxFontGroup
      12             : #include "gfxImageSurface.h"            // for gfxImageSurface
      13             : #include "gfxPoint.h"                   // for gfxSize
      14             : #include "mozilla/Attributes.h"         // for final
      15             : #include "mozilla/gfx/PathHelpers.h"
      16             : #include "mozilla/gfx/PrintTarget.h"
      17             : #include "mozilla/Preferences.h"        // for Preferences
      18             : #include "mozilla/Services.h"           // for GetObserverService
      19             : #include "mozilla/mozalloc.h"           // for operator new
      20             : #include "nsCRT.h"                      // for nsCRT
      21             : #include "nsDebug.h"                    // for NS_NOTREACHED, NS_ASSERTION, etc
      22             : #include "nsFont.h"                     // for nsFont
      23             : #include "nsFontMetrics.h"              // for nsFontMetrics
      24             : #include "nsIAtom.h"                    // for nsIAtom, NS_Atomize
      25             : #include "nsID.h"
      26             : #include "nsIDeviceContextSpec.h"       // for nsIDeviceContextSpec
      27             : #include "nsLanguageAtomService.h"      // for nsLanguageAtomService
      28             : #include "nsIObserver.h"                // for nsIObserver, etc
      29             : #include "nsIObserverService.h"         // for nsIObserverService
      30             : #include "nsIScreen.h"                  // for nsIScreen
      31             : #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
      32             : #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
      33             : #include "nsIWidget.h"                  // for nsIWidget, NS_NATIVE_WINDOW
      34             : #include "nsRect.h"                     // for nsRect
      35             : #include "nsServiceManagerUtils.h"      // for do_GetService
      36             : #include "nsString.h"               // for nsDependentString
      37             : #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
      38             : #include "nsThreadUtils.h"              // for NS_IsMainThread
      39             : #include "mozilla/gfx/Logging.h"
      40             : #include "mozilla/widget/ScreenManager.h" // for ScreenManager
      41             : 
      42             : using namespace mozilla;
      43             : using namespace mozilla::gfx;
      44             : using mozilla::services::GetObserverService;
      45             : using mozilla::widget::ScreenManager;
      46             : 
      47             : class nsFontCache final : public nsIObserver
      48             : {
      49             : public:
      50           5 :     nsFontCache() {}
      51             : 
      52             :     NS_DECL_ISUPPORTS
      53             :     NS_DECL_NSIOBSERVER
      54             : 
      55             :     void Init(nsDeviceContext* aContext);
      56             :     void Destroy();
      57             : 
      58             :     already_AddRefed<nsFontMetrics> GetMetricsFor(
      59             :         const nsFont& aFont, const nsFontMetrics::Params& aParams);
      60             : 
      61             :     void FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
      62             :     void Compact();
      63             :     void Flush();
      64             : 
      65             :     void UpdateUserFonts(gfxUserFontSet* aUserFontSet);
      66             : 
      67             : protected:
      68           0 :     ~nsFontCache() {}
      69             : 
      70             :     nsDeviceContext*          mContext; // owner
      71             :     nsCOMPtr<nsIAtom>         mLocaleLanguage;
      72             :     nsTArray<nsFontMetrics*>  mFontMetrics;
      73             : };
      74             : 
      75          10 : NS_IMPL_ISUPPORTS(nsFontCache, nsIObserver)
      76             : 
      77             : // The Init and Destroy methods are necessary because it's not
      78             : // safe to call AddObserver from a constructor or RemoveObserver
      79             : // from a destructor.  That should be fixed.
      80             : void
      81           5 : nsFontCache::Init(nsDeviceContext* aContext)
      82             : {
      83           5 :     mContext = aContext;
      84             :     // register as a memory-pressure observer to free font resources
      85             :     // in low-memory situations.
      86          10 :     nsCOMPtr<nsIObserverService> obs = GetObserverService();
      87           5 :     if (obs)
      88           5 :         obs->AddObserver(this, "memory-pressure", false);
      89             : 
      90           5 :     mLocaleLanguage = nsLanguageAtomService::GetService()->GetLocaleLanguage();
      91           5 :     if (!mLocaleLanguage) {
      92           0 :         mLocaleLanguage = NS_Atomize("x-western");
      93             :     }
      94           5 : }
      95             : 
      96             : void
      97           0 : nsFontCache::Destroy()
      98             : {
      99           0 :     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     100           0 :     if (obs)
     101           0 :         obs->RemoveObserver(this, "memory-pressure");
     102           0 :     Flush();
     103           0 : }
     104             : 
     105             : NS_IMETHODIMP
     106           0 : nsFontCache::Observe(nsISupports*, const char* aTopic, const char16_t*)
     107             : {
     108           0 :     if (!nsCRT::strcmp(aTopic, "memory-pressure"))
     109           0 :         Compact();
     110           0 :     return NS_OK;
     111             : }
     112             : 
     113             : already_AddRefed<nsFontMetrics>
     114         415 : nsFontCache::GetMetricsFor(const nsFont& aFont,
     115             :                            const nsFontMetrics::Params& aParams)
     116             : {
     117         415 :     nsIAtom* language = aParams.language ? aParams.language
     118         415 :                                          : mLocaleLanguage.get();
     119             : 
     120             :     // First check our cache
     121             :     // start from the end, which is where we put the most-recent-used element
     122             : 
     123         415 :     int32_t n = mFontMetrics.Length() - 1;
     124         415 :     for (int32_t i = n; i >= 0; --i) {
     125         409 :         nsFontMetrics* fm = mFontMetrics[i];
     126        1227 :         if (fm->Font().Equals(aFont) &&
     127         818 :             fm->GetUserFontSet() == aParams.userFontSet &&
     128        1227 :             fm->Language() == language &&
     129         409 :             fm->Orientation() == aParams.orientation) {
     130         409 :             if (i != n) {
     131             :                 // promote it to the end of the cache
     132           0 :                 mFontMetrics.RemoveElementAt(i);
     133           0 :                 mFontMetrics.AppendElement(fm);
     134             :             }
     135         409 :             fm->GetThebesFontGroup()->UpdateUserFonts();
     136         409 :             return do_AddRef(fm);
     137             :         }
     138             :     }
     139             : 
     140             :     // It's not in the cache. Get font metrics and then cache them.
     141             : 
     142           6 :     nsFontMetrics::Params params = aParams;
     143           6 :     params.language = language;
     144          12 :     RefPtr<nsFontMetrics> fm = new nsFontMetrics(aFont, params, mContext);
     145             :     // the mFontMetrics list has the "head" at the end, because append
     146             :     // is cheaper than insert
     147           6 :     mFontMetrics.AppendElement(do_AddRef(fm.get()).take());
     148           6 :     return fm.forget();
     149             : }
     150             : 
     151             : void
     152           0 : nsFontCache::UpdateUserFonts(gfxUserFontSet* aUserFontSet)
     153             : {
     154           0 :     for (nsFontMetrics* fm : mFontMetrics) {
     155           0 :         gfxFontGroup* fg = fm->GetThebesFontGroup();
     156           0 :         if (fg->GetUserFontSet() == aUserFontSet) {
     157           0 :             fg->UpdateUserFonts();
     158             :         }
     159             :     }
     160           0 : }
     161             : 
     162             : void
     163           0 : nsFontCache::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
     164             : {
     165           0 :     mFontMetrics.RemoveElement(aFontMetrics);
     166           0 : }
     167             : 
     168             : void
     169           0 : nsFontCache::Compact()
     170             : {
     171             :     // Need to loop backward because the running element can be removed on
     172             :     // the way
     173           0 :     for (int32_t i = mFontMetrics.Length()-1; i >= 0; --i) {
     174           0 :         nsFontMetrics* fm = mFontMetrics[i];
     175           0 :         nsFontMetrics* oldfm = fm;
     176             :         // Destroy() isn't here because we want our device context to be
     177             :         // notified
     178           0 :         NS_RELEASE(fm); // this will reset fm to nullptr
     179             :         // if the font is really gone, it would have called back in
     180             :         // FontMetricsDeleted() and would have removed itself
     181           0 :         if (mFontMetrics.IndexOf(oldfm) != mFontMetrics.NoIndex) {
     182             :             // nope, the font is still there, so let's hold onto it too
     183           0 :             NS_ADDREF(oldfm);
     184             :         }
     185             :     }
     186           0 : }
     187             : 
     188             : void
     189           1 : nsFontCache::Flush()
     190             : {
     191           2 :     for (int32_t i = mFontMetrics.Length()-1; i >= 0; --i) {
     192           1 :         nsFontMetrics* fm = mFontMetrics[i];
     193             :         // Destroy() will unhook our device context from the fm so that we
     194             :         // won't waste time in triggering the notification of
     195             :         // FontMetricsDeleted() in the subsequent release
     196           1 :         fm->Destroy();
     197           1 :         NS_RELEASE(fm);
     198             :     }
     199           1 :     mFontMetrics.Clear();
     200           1 : }
     201             : 
     202          29 : nsDeviceContext::nsDeviceContext()
     203             :     : mWidth(0), mHeight(0),
     204             :       mAppUnitsPerDevPixel(-1), mAppUnitsPerDevPixelAtUnitFullZoom(-1),
     205             :       mAppUnitsPerPhysicalInch(-1),
     206             :       mFullZoom(1.0f), mPrintingScale(1.0f),
     207             :       mIsCurrentlyPrintingDoc(false)
     208             : #ifdef DEBUG
     209          29 :     , mIsInitialized(false)
     210             : #endif
     211             : {
     212          29 :     MOZ_ASSERT(NS_IsMainThread(), "nsDeviceContext created off main thread");
     213          29 : }
     214             : 
     215           0 : nsDeviceContext::~nsDeviceContext()
     216             : {
     217           0 :     if (mFontCache) {
     218           0 :         mFontCache->Destroy();
     219             :     }
     220           0 : }
     221             : 
     222             : void
     223         415 : nsDeviceContext::InitFontCache()
     224             : {
     225         415 :     if (!mFontCache) {
     226           5 :         mFontCache = new nsFontCache();
     227           5 :         mFontCache->Init(this);
     228             :     }
     229         415 : }
     230             : 
     231             : void
     232           0 : nsDeviceContext::UpdateFontCacheUserFonts(gfxUserFontSet* aUserFontSet)
     233             : {
     234           0 :     if (mFontCache) {
     235           0 :         mFontCache->UpdateUserFonts(aUserFontSet);
     236             :     }
     237           0 : }
     238             : 
     239             : already_AddRefed<nsFontMetrics>
     240         415 : nsDeviceContext::GetMetricsFor(const nsFont& aFont,
     241             :                                const nsFontMetrics::Params& aParams)
     242             : {
     243         415 :     InitFontCache();
     244         415 :     return mFontCache->GetMetricsFor(aFont, aParams);
     245             : }
     246             : 
     247             : nsresult
     248           3 : nsDeviceContext::FlushFontCache(void)
     249             : {
     250           3 :     if (mFontCache)
     251           1 :         mFontCache->Flush();
     252           3 :     return NS_OK;
     253             : }
     254             : 
     255             : nsresult
     256           0 : nsDeviceContext::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
     257             : {
     258           0 :     if (mFontCache) {
     259           0 :         mFontCache->FontMetricsDeleted(aFontMetrics);
     260             :     }
     261           0 :     return NS_OK;
     262             : }
     263             : 
     264             : bool
     265          20 : nsDeviceContext::IsPrinterContext()
     266             : {
     267          20 :   return mPrintTarget != nullptr;
     268             : }
     269             : 
     270             : void
     271          82 : nsDeviceContext::SetDPI(double* aScale)
     272             : {
     273          82 :     float dpi = -1.0f;
     274             : 
     275             :     // Use the printing DC to determine DPI values, if we have one.
     276          82 :     if (mDeviceContextSpec) {
     277           0 :         dpi = mDeviceContextSpec->GetDPI();
     278           0 :         mPrintingScale = mDeviceContextSpec->GetPrintingScale();
     279           0 :         mAppUnitsPerDevPixelAtUnitFullZoom =
     280           0 :             NS_lround((AppUnitsPerCSSPixel() * 96) / dpi);
     281             :     } else {
     282             :         // A value of -1 means use the maximum of 96 and the system DPI.
     283             :         // A value of 0 means use the system DPI. A positive value is used as the DPI.
     284             :         // This sets the physical size of a device pixel and thus controls the
     285             :         // interpretation of physical units.
     286          82 :         int32_t prefDPI = Preferences::GetInt("layout.css.dpi", -1);
     287             : 
     288          82 :         if (prefDPI > 0) {
     289           0 :             dpi = prefDPI;
     290          82 :         } else if (mWidget) {
     291          42 :             dpi = mWidget->GetDPI();
     292             : 
     293          42 :             if (prefDPI < 0) {
     294          42 :                 dpi = std::max(96.0f, dpi);
     295             :             }
     296             :         } else {
     297          40 :             dpi = 96.0f;
     298             :         }
     299             : 
     300             :         double devPixelsPerCSSPixel;
     301          82 :         if (aScale && *aScale > 0.0) {
     302             :             // if caller provided a scale, we just use it
     303           0 :             devPixelsPerCSSPixel = *aScale;
     304             :         } else {
     305             :             // otherwise get from the widget, and return it in aScale for
     306             :             // the caller to pass to child contexts if needed
     307             :             CSSToLayoutDeviceScale scale =
     308             :                 mWidget ? mWidget->GetDefaultScale()
     309          82 :                         : CSSToLayoutDeviceScale(1.0);
     310          82 :             devPixelsPerCSSPixel = scale.scale;
     311          82 :             if (aScale) {
     312           1 :                 *aScale = devPixelsPerCSSPixel;
     313             :             }
     314             :         }
     315             : 
     316          82 :         mAppUnitsPerDevPixelAtUnitFullZoom =
     317         164 :             std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
     318             :     }
     319             : 
     320          82 :     NS_ASSERTION(dpi != -1.0, "no dpi set");
     321             : 
     322          82 :     mAppUnitsPerPhysicalInch = NS_lround(dpi * mAppUnitsPerDevPixelAtUnitFullZoom);
     323          82 :     UpdateAppUnitsForFullZoom();
     324          82 : }
     325             : 
     326             : nsresult
     327          29 : nsDeviceContext::Init(nsIWidget *aWidget)
     328             : {
     329             : #ifdef DEBUG
     330             :     // We can't assert |!mIsInitialized| here since EndSwapDocShellsForDocument
     331             :     // re-initializes nsDeviceContext objects.  We can only assert in
     332             :     // InitForPrinting (below).
     333          29 :     mIsInitialized = true;
     334             : #endif
     335             : 
     336          29 :     nsresult rv = NS_OK;
     337          29 :     if (mScreenManager && mWidget == aWidget)
     338           0 :         return rv;
     339             : 
     340          29 :     mWidget = aWidget;
     341          29 :     SetDPI();
     342             : 
     343          29 :     if (mScreenManager)
     344           0 :         return rv;
     345             : 
     346          29 :     mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1", &rv);
     347             : 
     348          29 :     return rv;
     349             : }
     350             : 
     351             : // XXX This is only for printing. We should make that obvious in the name.
     352             : already_AddRefed<gfxContext>
     353           0 : nsDeviceContext::CreateRenderingContext()
     354             : {
     355           0 :   return CreateRenderingContextCommon(/* not a reference context */ false);
     356             : }
     357             : 
     358             : already_AddRefed<gfxContext>
     359           0 : nsDeviceContext::CreateReferenceRenderingContext()
     360             : {
     361           0 :   return CreateRenderingContextCommon(/* a reference context */ true);
     362             : }
     363             : 
     364             : already_AddRefed<gfxContext>
     365           0 : nsDeviceContext::CreateRenderingContextCommon(bool aWantReferenceContext)
     366             : {
     367           0 :     MOZ_ASSERT(IsPrinterContext());
     368           0 :     MOZ_ASSERT(mWidth > 0 && mHeight > 0);
     369             : 
     370             :     // This will usually be null, depending on the pref print.print_via_parent.
     371           0 :     RefPtr<DrawEventRecorder> recorder;
     372           0 :     mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder));
     373             : 
     374           0 :     RefPtr<gfx::DrawTarget> dt;
     375           0 :     if (aWantReferenceContext) {
     376           0 :       dt = mPrintTarget->GetReferenceDrawTarget(recorder);
     377             :     } else {
     378           0 :       dt = mPrintTarget->MakeDrawTarget(gfx::IntSize(mWidth, mHeight), recorder);
     379             :     }
     380             : 
     381           0 :     if (!dt || !dt->IsValid()) {
     382           0 :       gfxCriticalNote
     383           0 :         << "Failed to create draw target in device context sized "
     384           0 :         << mWidth << "x" << mHeight << " and pointer "
     385           0 :         << hexa(mPrintTarget);
     386           0 :       return nullptr;
     387             :     }
     388             : 
     389             : #ifdef XP_MACOSX
     390             :     // The CGContextRef provided by PMSessionGetCGGraphicsContext is
     391             :     // write-only, so we need to prevent gfxContext::PushGroupAndCopyBackground
     392             :     // trying to read from it or else we'll crash.
     393             :     // XXXjwatt Consider adding a MakeDrawTarget override to PrintTargetCG and
     394             :     // moving this AddUserData call there.
     395             :     dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
     396             : #endif
     397           0 :     dt->AddUserData(&sDisablePixelSnapping, (void*)0x1, nullptr);
     398             : 
     399           0 :     RefPtr<gfxContext> pContext = gfxContext::CreateOrNull(dt);
     400           0 :     MOZ_ASSERT(pContext); // already checked draw target above
     401             : 
     402           0 :     gfxMatrix transform;
     403           0 :     if (mPrintTarget->RotateNeededForLandscape()) {
     404             :       // Rotate page 90 degrees to draw landscape page on portrait paper
     405           0 :       IntSize size = mPrintTarget->GetSize();
     406           0 :       transform.PreTranslate(gfxPoint(0, size.width));
     407             :       gfxMatrix rotate(0, -1,
     408             :                        1,  0,
     409           0 :                        0,  0);
     410           0 :       transform = rotate * transform;
     411             :     }
     412           0 :     transform.PreScale(mPrintingScale, mPrintingScale);
     413             : 
     414           0 :     pContext->SetMatrix(transform);
     415           0 :     return pContext.forget();
     416             : }
     417             : 
     418             : nsresult
     419           0 : nsDeviceContext::GetDepth(uint32_t& aDepth)
     420             : {
     421           0 :     nsCOMPtr<nsIScreen> screen;
     422           0 :     FindScreen(getter_AddRefs(screen));
     423           0 :     if (!screen) {
     424           0 :         ScreenManager& screenManager = ScreenManager::GetSingleton();
     425           0 :         screenManager.GetPrimaryScreen(getter_AddRefs(screen));
     426           0 :         MOZ_ASSERT(screen);
     427             :     }
     428           0 :     screen->GetColorDepth(reinterpret_cast<int32_t *>(&aDepth));
     429             : 
     430           0 :     return NS_OK;
     431             : }
     432             : 
     433             : nsresult
     434           0 : nsDeviceContext::GetDeviceSurfaceDimensions(nscoord &aWidth, nscoord &aHeight)
     435             : {
     436           0 :     if (IsPrinterContext()) {
     437           0 :         aWidth = mWidth;
     438           0 :         aHeight = mHeight;
     439             :     } else {
     440           0 :         nsRect area;
     441           0 :         ComputeFullAreaUsingScreen(&area);
     442           0 :         aWidth = area.width;
     443           0 :         aHeight = area.height;
     444             :     }
     445             : 
     446           0 :     return NS_OK;
     447             : }
     448             : 
     449             : nsresult
     450          10 : nsDeviceContext::GetRect(nsRect &aRect)
     451             : {
     452          10 :     if (IsPrinterContext()) {
     453           0 :         aRect.x = 0;
     454           0 :         aRect.y = 0;
     455           0 :         aRect.width = mWidth;
     456           0 :         aRect.height = mHeight;
     457             :     } else
     458          10 :         ComputeFullAreaUsingScreen ( &aRect );
     459             : 
     460          10 :     return NS_OK;
     461             : }
     462             : 
     463             : nsresult
     464           4 : nsDeviceContext::GetClientRect(nsRect &aRect)
     465             : {
     466           4 :     if (IsPrinterContext()) {
     467           0 :         aRect.x = 0;
     468           0 :         aRect.y = 0;
     469           0 :         aRect.width = mWidth;
     470           0 :         aRect.height = mHeight;
     471             :     }
     472             :     else
     473           4 :         ComputeClientRectUsingScreen(&aRect);
     474             : 
     475           4 :     return NS_OK;
     476             : }
     477             : 
     478             : nsresult
     479           0 : nsDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice)
     480             : {
     481           0 :     NS_ENSURE_ARG_POINTER(aDevice);
     482             : 
     483           0 :     MOZ_ASSERT(!mIsInitialized,
     484             :                "Only initialize once, immediately after construction");
     485             : 
     486             :     // We don't set mIsInitialized here. The Init() call below does that.
     487             : 
     488           0 :     mPrintTarget = aDevice->MakePrintTarget();
     489           0 :     if (!mPrintTarget) {
     490           0 :         return NS_ERROR_FAILURE;
     491             :     }
     492             : 
     493           0 :     mDeviceContextSpec = aDevice;
     494             : 
     495           0 :     Init(nullptr);
     496             : 
     497           0 :     if (!CalcPrintingSize()) {
     498           0 :         return NS_ERROR_FAILURE;
     499             :     }
     500             : 
     501           0 :     return NS_OK;
     502             : }
     503             : 
     504             : nsresult
     505           0 : nsDeviceContext::BeginDocument(const nsAString& aTitle,
     506             :                                const nsAString& aPrintToFileName,
     507             :                                int32_t          aStartPage,
     508             :                                int32_t          aEndPage)
     509             : {
     510           0 :     MOZ_ASSERT(!mIsCurrentlyPrintingDoc,
     511             :                "Mismatched BeginDocument/EndDocument calls");
     512             : 
     513           0 :     nsresult rv = mPrintTarget->BeginPrinting(aTitle, aPrintToFileName,
     514           0 :                                               aStartPage, aEndPage);
     515             : 
     516           0 :     if (NS_SUCCEEDED(rv)) {
     517           0 :         if (mDeviceContextSpec) {
     518           0 :            rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName,
     519           0 :                                                   aStartPage, aEndPage);
     520             :         }
     521           0 :         mIsCurrentlyPrintingDoc = true;
     522             :     }
     523             : 
     524           0 :     return rv;
     525             : }
     526             : 
     527             : 
     528             : nsresult
     529           0 : nsDeviceContext::EndDocument(void)
     530             : {
     531           0 :     MOZ_ASSERT(mIsCurrentlyPrintingDoc,
     532             :                "Mismatched BeginDocument/EndDocument calls");
     533             : 
     534           0 :     nsresult rv = NS_OK;
     535             : 
     536           0 :     mIsCurrentlyPrintingDoc = false;
     537             : 
     538           0 :     rv = mPrintTarget->EndPrinting();
     539           0 :     if (NS_SUCCEEDED(rv)) {
     540           0 :         mPrintTarget->Finish();
     541             :     }
     542             : 
     543           0 :     if (mDeviceContextSpec)
     544           0 :         mDeviceContextSpec->EndDocument();
     545             : 
     546           0 :     mPrintTarget = nullptr;
     547             : 
     548           0 :     return rv;
     549             : }
     550             : 
     551             : 
     552             : nsresult
     553           0 : nsDeviceContext::AbortDocument(void)
     554             : {
     555           0 :     MOZ_ASSERT(mIsCurrentlyPrintingDoc,
     556             :                "Mismatched BeginDocument/EndDocument calls");
     557             : 
     558           0 :     nsresult rv = mPrintTarget->AbortPrinting();
     559             : 
     560           0 :     mIsCurrentlyPrintingDoc = false;
     561             : 
     562           0 :     if (mDeviceContextSpec)
     563           0 :         mDeviceContextSpec->EndDocument();
     564             : 
     565           0 :     mPrintTarget = nullptr;
     566             : 
     567           0 :     return rv;
     568             : }
     569             : 
     570             : 
     571             : nsresult
     572           0 : nsDeviceContext::BeginPage(void)
     573             : {
     574           0 :     nsresult rv = NS_OK;
     575             : 
     576           0 :     if (mDeviceContextSpec)
     577           0 :         rv = mDeviceContextSpec->BeginPage();
     578             : 
     579           0 :     if (NS_FAILED(rv)) return rv;
     580             : 
     581           0 :     return mPrintTarget->BeginPage();
     582             : }
     583             : 
     584             : nsresult
     585           0 : nsDeviceContext::EndPage(void)
     586             : {
     587           0 :     nsresult rv = mPrintTarget->EndPage();
     588             : 
     589           0 :     if (mDeviceContextSpec)
     590           0 :         mDeviceContextSpec->EndPage();
     591             : 
     592           0 :     return rv;
     593             : }
     594             : 
     595             : void
     596           4 : nsDeviceContext::ComputeClientRectUsingScreen(nsRect* outRect)
     597             : {
     598             :     // we always need to recompute the clientRect
     599             :     // because the window may have moved onto a different screen. In the single
     600             :     // monitor case, we only need to do the computation if we haven't done it
     601             :     // once already, and remember that we have because we're assured it won't change.
     602           8 :     nsCOMPtr<nsIScreen> screen;
     603           4 :     FindScreen (getter_AddRefs(screen));
     604           4 :     if (screen) {
     605             :         int32_t x, y, width, height;
     606           4 :         screen->GetAvailRect(&x, &y, &width, &height);
     607             : 
     608             :         // convert to device units
     609           4 :         outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
     610           4 :         outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
     611           4 :         outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
     612           4 :         outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
     613             :     }
     614           4 : }
     615             : 
     616             : void
     617          10 : nsDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
     618             : {
     619             :     // if we have more than one screen, we always need to recompute the clientRect
     620             :     // because the window may have moved onto a different screen. In the single
     621             :     // monitor case, we only need to do the computation if we haven't done it
     622             :     // once already, and remember that we have because we're assured it won't change.
     623          20 :     nsCOMPtr<nsIScreen> screen;
     624          10 :     FindScreen ( getter_AddRefs(screen) );
     625          10 :     if ( screen ) {
     626             :         int32_t x, y, width, height;
     627          10 :         screen->GetRect ( &x, &y, &width, &height );
     628             : 
     629             :         // convert to device units
     630          10 :         outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
     631          10 :         outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
     632          10 :         outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
     633          10 :         outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
     634             : 
     635          10 :         mWidth = outRect->width;
     636          10 :         mHeight = outRect->height;
     637             :     }
     638          10 : }
     639             : 
     640             : //
     641             : // FindScreen
     642             : //
     643             : // Determines which screen intersects the largest area of the given surface.
     644             : //
     645             : void
     646          24 : nsDeviceContext::FindScreen(nsIScreen** outScreen)
     647             : {
     648          24 :     if (!mWidget || !mScreenManager) {
     649           0 :         return;
     650             :     }
     651             : 
     652          24 :     CheckDPIChange();
     653             : 
     654          48 :     nsCOMPtr<nsIScreen> screen = mWidget->GetWidgetScreen();
     655          24 :     screen.forget(outScreen);
     656             : 
     657          24 :     if (!(*outScreen)) {
     658           0 :         mScreenManager->GetPrimaryScreen(outScreen);
     659             :     }
     660             : }
     661             : 
     662             : bool
     663           0 : nsDeviceContext::CalcPrintingSize()
     664             : {
     665           0 :     gfxSize size(mPrintTarget->GetSize());
     666             :     // For printing, CSS inches and physical inches are identical
     667             :     // so it doesn't matter which we use here
     668           0 :     mWidth = NSToCoordRound(size.width * AppUnitsPerPhysicalInch()
     669             :                             / POINTS_PER_INCH_FLOAT);
     670           0 :     mHeight = NSToCoordRound(size.height * AppUnitsPerPhysicalInch()
     671             :                              / POINTS_PER_INCH_FLOAT);
     672             : 
     673           0 :     return (mWidth > 0 && mHeight > 0);
     674             : }
     675             : 
     676          53 : bool nsDeviceContext::CheckDPIChange(double* aScale)
     677             : {
     678          53 :     int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom;
     679          53 :     int32_t oldInches = mAppUnitsPerPhysicalInch;
     680             : 
     681          53 :     SetDPI(aScale);
     682             : 
     683         105 :     return oldDevPixels != mAppUnitsPerDevPixelAtUnitFullZoom ||
     684         105 :         oldInches != mAppUnitsPerPhysicalInch;
     685             : }
     686             : 
     687             : bool
     688          28 : nsDeviceContext::SetFullZoom(float aScale)
     689             : {
     690          28 :     if (aScale <= 0) {
     691           0 :         NS_NOTREACHED("Invalid full zoom value");
     692           0 :         return false;
     693             :     }
     694          28 :     int32_t oldAppUnitsPerDevPixel = mAppUnitsPerDevPixel;
     695          28 :     mFullZoom = aScale;
     696          28 :     UpdateAppUnitsForFullZoom();
     697          28 :     return oldAppUnitsPerDevPixel != mAppUnitsPerDevPixel;
     698             : }
     699             : 
     700             : void
     701         110 : nsDeviceContext::UpdateAppUnitsForFullZoom()
     702             : {
     703         110 :     mAppUnitsPerDevPixel =
     704         220 :         std::max(1, NSToIntRound(float(mAppUnitsPerDevPixelAtUnitFullZoom) / mFullZoom));
     705             :     // adjust mFullZoom to reflect appunit rounding
     706         110 :     mFullZoom = float(mAppUnitsPerDevPixelAtUnitFullZoom) / mAppUnitsPerDevPixel;
     707         110 : }
     708             : 
     709             : DesktopToLayoutDeviceScale
     710          10 : nsDeviceContext::GetDesktopToDeviceScale()
     711             : {
     712          20 :     nsCOMPtr<nsIScreen> screen;
     713          10 :     FindScreen(getter_AddRefs(screen));
     714             : 
     715          10 :     if (screen) {
     716             :         double scale;
     717          10 :         screen->GetContentsScaleFactor(&scale);
     718          10 :         return DesktopToLayoutDeviceScale(scale);
     719             :     }
     720             : 
     721           0 :     return DesktopToLayoutDeviceScale(1.0);
     722             : }

Generated by: LCOV version 1.13