LCOV - code coverage report
Current view: directory - gfx/src - nsDeviceContext.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 293 0 0.0 %
Date: 2012-06-02 Functions: 38 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is thebes gfx
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * mozilla.org.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      24                 :  *   Stuart Parmenter <pavlov@pavlov.net>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsDeviceContext.h"
      41                 : #include "nsCRT.h"
      42                 : #include "nsFontMetrics.h"
      43                 : #include "nsRenderingContext.h"
      44                 : #include "nsIView.h"
      45                 : #include "nsIWidget.h"
      46                 : 
      47                 : #include "mozilla/Attributes.h"
      48                 : #include "mozilla/Services.h"
      49                 : #include "mozilla/Preferences.h"
      50                 : #include "nsIServiceManager.h"
      51                 : #include "nsILanguageAtomService.h"
      52                 : #include "nsIObserver.h"
      53                 : #include "nsIObserverService.h"
      54                 : 
      55                 : #include "gfxImageSurface.h"
      56                 : 
      57                 : #if !XP_MACOSX
      58                 : #include "gfxPDFSurface.h"
      59                 : #endif
      60                 : 
      61                 : #ifdef MOZ_ENABLE_GTK2
      62                 : #include "gfxPSSurface.h"
      63                 : #elif XP_WIN
      64                 : #include "gfxWindowsSurface.h"
      65                 : #elif defined(XP_OS2)
      66                 : #include "gfxOS2Surface.h"
      67                 : #elif XP_MACOSX
      68                 : #include "gfxQuartzSurface.h"
      69                 : #endif
      70                 : 
      71                 : using namespace mozilla;
      72                 : using mozilla::services::GetObserverService;
      73                 : 
      74                 : class nsFontCache MOZ_FINAL : public nsIObserver
      75                 : {
      76                 : public:
      77               0 :     nsFontCache()   { MOZ_COUNT_CTOR(nsFontCache); }
      78               0 :     ~nsFontCache()  { MOZ_COUNT_DTOR(nsFontCache); }
      79                 : 
      80                 :     NS_DECL_ISUPPORTS
      81                 :     NS_DECL_NSIOBSERVER
      82                 : 
      83                 :     void Init(nsDeviceContext* aContext);
      84                 :     void Destroy();
      85                 : 
      86                 :     nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
      87                 :                            gfxUserFontSet* aUserFontSet,
      88                 :                            nsFontMetrics*& aMetrics);
      89                 : 
      90                 :     void FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
      91                 :     void Compact();
      92                 :     void Flush();
      93                 : 
      94                 : protected:
      95                 :     nsDeviceContext*          mContext; // owner
      96                 :     nsCOMPtr<nsIAtom>         mLocaleLanguage;
      97                 :     nsTArray<nsFontMetrics*>  mFontMetrics;
      98                 : };
      99                 : 
     100               0 : NS_IMPL_ISUPPORTS1(nsFontCache, nsIObserver)
     101                 : 
     102                 : // The Init and Destroy methods are necessary because it's not
     103                 : // safe to call AddObserver from a constructor or RemoveObserver
     104                 : // from a destructor.  That should be fixed.
     105                 : void
     106               0 : nsFontCache::Init(nsDeviceContext* aContext)
     107                 : {
     108               0 :     mContext = aContext;
     109                 :     // register as a memory-pressure observer to free font resources
     110                 :     // in low-memory situations.
     111               0 :     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     112               0 :     if (obs)
     113               0 :         obs->AddObserver(this, "memory-pressure", false);
     114                 : 
     115               0 :     nsCOMPtr<nsILanguageAtomService> langService;
     116               0 :     langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
     117               0 :     if (langService) {
     118               0 :         mLocaleLanguage = langService->GetLocaleLanguage();
     119                 :     }
     120               0 :     if (!mLocaleLanguage) {
     121               0 :         mLocaleLanguage = do_GetAtom("x-western");
     122                 :     }
     123               0 : }
     124                 : 
     125                 : void
     126               0 : nsFontCache::Destroy()
     127                 : {
     128               0 :     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     129               0 :     if (obs)
     130               0 :         obs->RemoveObserver(this, "memory-pressure");
     131               0 :     Flush();
     132               0 : }
     133                 : 
     134                 : NS_IMETHODIMP
     135               0 : nsFontCache::Observe(nsISupports*, const char* aTopic, const PRUnichar*)
     136                 : {
     137               0 :     if (!nsCRT::strcmp(aTopic, "memory-pressure"))
     138               0 :         Compact();
     139               0 :     return NS_OK;
     140                 : }
     141                 : 
     142                 : nsresult
     143               0 : nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
     144                 :                            gfxUserFontSet* aUserFontSet,
     145                 :                            nsFontMetrics*& aMetrics)
     146                 : {
     147               0 :     if (!aLanguage)
     148               0 :         aLanguage = mLocaleLanguage;
     149                 : 
     150                 :     // First check our cache
     151                 :     // start from the end, which is where we put the most-recent-used element
     152                 : 
     153                 :     nsFontMetrics* fm;
     154               0 :     PRInt32 n = mFontMetrics.Length() - 1;
     155               0 :     for (PRInt32 i = n; i >= 0; --i) {
     156               0 :         fm = mFontMetrics[i];
     157               0 :         if (fm->Font().Equals(aFont) && fm->GetUserFontSet() == aUserFontSet &&
     158               0 :             fm->Language() == aLanguage) {
     159               0 :             if (i != n) {
     160                 :                 // promote it to the end of the cache
     161               0 :                 mFontMetrics.RemoveElementAt(i);
     162               0 :                 mFontMetrics.AppendElement(fm);
     163                 :             }
     164               0 :             fm->GetThebesFontGroup()->UpdateFontList();
     165               0 :             NS_ADDREF(aMetrics = fm);
     166               0 :             return NS_OK;
     167                 :         }
     168                 :     }
     169                 : 
     170                 :     // It's not in the cache. Get font metrics and then cache them.
     171                 : 
     172               0 :     fm = new nsFontMetrics();
     173               0 :     NS_ADDREF(fm);
     174               0 :     nsresult rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     175               0 :     if (NS_SUCCEEDED(rv)) {
     176                 :         // the mFontMetrics list has the "head" at the end, because append
     177                 :         // is cheaper than insert
     178               0 :         mFontMetrics.AppendElement(fm);
     179               0 :         aMetrics = fm;
     180               0 :         NS_ADDREF(aMetrics);
     181               0 :         return NS_OK;
     182                 :     }
     183               0 :     fm->Destroy();
     184               0 :     NS_RELEASE(fm);
     185                 : 
     186                 :     // One reason why Init() fails is because the system is running out of
     187                 :     // resources. e.g., on Win95/98 only a very limited number of GDI
     188                 :     // objects are available. Compact the cache and try again.
     189                 : 
     190               0 :     Compact();
     191               0 :     fm = new nsFontMetrics();
     192               0 :     NS_ADDREF(fm);
     193               0 :     rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     194               0 :     if (NS_SUCCEEDED(rv)) {
     195               0 :         mFontMetrics.AppendElement(fm);
     196               0 :         aMetrics = fm;
     197               0 :         return NS_OK;
     198                 :     }
     199               0 :     fm->Destroy();
     200               0 :     NS_RELEASE(fm);
     201                 : 
     202                 :     // could not setup a new one, send an old one (XXX search a "best
     203                 :     // match"?)
     204                 : 
     205               0 :     n = mFontMetrics.Length() - 1; // could have changed in Compact()
     206               0 :     if (n >= 0) {
     207               0 :         aMetrics = mFontMetrics[n];
     208               0 :         NS_ADDREF(aMetrics);
     209               0 :         return NS_OK;
     210                 :     }
     211                 : 
     212               0 :     NS_POSTCONDITION(NS_SUCCEEDED(rv),
     213                 :                      "font metrics should not be null - bug 136248");
     214               0 :     return rv;
     215                 : }
     216                 : 
     217                 : void
     218               0 : nsFontCache::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
     219                 : {
     220               0 :     mFontMetrics.RemoveElement(aFontMetrics);
     221               0 : }
     222                 : 
     223                 : void
     224               0 : nsFontCache::Compact()
     225                 : {
     226                 :     // Need to loop backward because the running element can be removed on
     227                 :     // the way
     228               0 :     for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
     229               0 :         nsFontMetrics* fm = mFontMetrics[i];
     230               0 :         nsFontMetrics* oldfm = fm;
     231                 :         // Destroy() isn't here because we want our device context to be
     232                 :         // notified
     233               0 :         NS_RELEASE(fm); // this will reset fm to nsnull
     234                 :         // if the font is really gone, it would have called back in
     235                 :         // FontMetricsDeleted() and would have removed itself
     236               0 :         if (mFontMetrics.IndexOf(oldfm) != mFontMetrics.NoIndex) {
     237                 :             // nope, the font is still there, so let's hold onto it too
     238               0 :             NS_ADDREF(oldfm);
     239                 :         }
     240                 :     }
     241               0 : }
     242                 : 
     243                 : void
     244               0 : nsFontCache::Flush()
     245                 : {
     246               0 :     for (PRInt32 i = mFontMetrics.Length()-1; i >= 0; --i) {
     247               0 :         nsFontMetrics* fm = mFontMetrics[i];
     248                 :         // Destroy() will unhook our device context from the fm so that we
     249                 :         // won't waste time in triggering the notification of
     250                 :         // FontMetricsDeleted() in the subsequent release
     251               0 :         fm->Destroy();
     252               0 :         NS_RELEASE(fm);
     253                 :     }
     254               0 :     mFontMetrics.Clear();
     255               0 : }
     256                 : 
     257               0 : nsDeviceContext::nsDeviceContext()
     258                 :     : mWidth(0), mHeight(0), mDepth(0),
     259                 :       mAppUnitsPerDevPixel(-1), mAppUnitsPerDevNotScaledPixel(-1),
     260                 :       mAppUnitsPerPhysicalInch(-1),
     261                 :       mPixelScale(1.0f), mPrintingScale(1.0f),
     262               0 :       mFontCache(nsnull)
     263                 : {
     264               0 : }
     265                 : 
     266                 : // Note: we use a bare pointer for mFontCache so that nsFontCache
     267                 : // can be an incomplete type in nsDeviceContext.h.
     268                 : // Therefore we have to do all the refcounting by hand.
     269               0 : nsDeviceContext::~nsDeviceContext()
     270                 : {
     271               0 :     if (mFontCache) {
     272               0 :         mFontCache->Destroy();
     273               0 :         NS_RELEASE(mFontCache);
     274                 :     }
     275               0 : }
     276                 : 
     277                 : nsresult
     278               0 : nsDeviceContext::GetMetricsFor(const nsFont& aFont,
     279                 :                                nsIAtom* aLanguage,
     280                 :                                gfxUserFontSet* aUserFontSet,
     281                 :                                nsFontMetrics*& aMetrics)
     282                 : {
     283               0 :     if (!mFontCache) {
     284               0 :         mFontCache = new nsFontCache();
     285               0 :         NS_ADDREF(mFontCache);
     286               0 :         mFontCache->Init(this);
     287                 :     }
     288                 : 
     289               0 :     return mFontCache->GetMetricsFor(aFont, aLanguage, aUserFontSet, aMetrics);
     290                 : }
     291                 : 
     292                 : nsresult
     293               0 : nsDeviceContext::FlushFontCache(void)
     294                 : {
     295               0 :     if (mFontCache)
     296               0 :         mFontCache->Flush();
     297               0 :     return NS_OK;
     298                 : }
     299                 : 
     300                 : nsresult
     301               0 : nsDeviceContext::FontMetricsDeleted(const nsFontMetrics* aFontMetrics)
     302                 : {
     303               0 :     if (mFontCache) {
     304               0 :         mFontCache->FontMetricsDeleted(aFontMetrics);
     305                 :     }
     306               0 :     return NS_OK;
     307                 : }
     308                 : 
     309                 : bool
     310               0 : nsDeviceContext::IsPrinterSurface()
     311                 : {
     312               0 :     return(mPrintingSurface != NULL);
     313                 : }
     314                 : 
     315                 : void
     316               0 : nsDeviceContext::SetDPI()
     317                 : {
     318               0 :     float dpi = -1.0f;
     319                 : 
     320                 :     // PostScript, PDF and Mac (when printing) all use 72 dpi
     321                 :     // Use a printing DC to determine the other dpi values
     322               0 :     if (mPrintingSurface) {
     323               0 :         switch (mPrintingSurface->GetType()) {
     324                 :         case gfxASurface::SurfaceTypePDF:
     325                 :         case gfxASurface::SurfaceTypePS:
     326                 :         case gfxASurface::SurfaceTypeQuartz:
     327               0 :             dpi = 72.0f;
     328               0 :             break;
     329                 : #ifdef XP_WIN
     330                 :         case gfxASurface::SurfaceTypeWin32:
     331                 :         case gfxASurface::SurfaceTypeWin32Printing: {
     332                 :             HDC dc = reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
     333                 :             PRInt32 OSVal = GetDeviceCaps(dc, LOGPIXELSY);
     334                 :             dpi = 144.0f;
     335                 :             mPrintingScale = float(OSVal) / dpi;
     336                 :             break;
     337                 :         }
     338                 : #endif
     339                 : #ifdef XP_OS2
     340                 :         case gfxASurface::SurfaceTypeOS2: {
     341                 :             LONG lDPI;
     342                 :             HDC dc = GpiQueryDevice(reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetPS());
     343                 :             if (DevQueryCaps(dc, CAPS_VERTICAL_FONT_RES, 1, &lDPI))
     344                 :                 dpi = lDPI;
     345                 :             break;
     346                 :         }
     347                 : #endif
     348                 :         default:
     349               0 :             NS_NOTREACHED("Unexpected printing surface type");
     350               0 :             break;
     351                 :         }
     352                 : 
     353                 :         mAppUnitsPerDevNotScaledPixel =
     354               0 :             NS_lround((AppUnitsPerCSSPixel() * 96) / dpi);
     355                 :     } else {
     356                 :         // A value of -1 means use the maximum of 96 and the system DPI.
     357                 :         // A value of 0 means use the system DPI. A positive value is used as the DPI.
     358                 :         // This sets the physical size of a device pixel and thus controls the
     359                 :         // interpretation of physical units.
     360               0 :         PRInt32 prefDPI = Preferences::GetInt("layout.css.dpi", -1);
     361                 : 
     362               0 :         if (prefDPI > 0) {
     363               0 :             dpi = prefDPI;
     364               0 :         } else if (mWidget) {
     365               0 :             dpi = mWidget->GetDPI();
     366                 : 
     367               0 :             if (prefDPI < 0) {
     368               0 :                 dpi = NS_MAX(96.0f, dpi);
     369                 :             }
     370                 :         } else {
     371               0 :             dpi = 96.0f;
     372                 :         }
     373                 : 
     374                 :         // The number of device pixels per CSS pixel. A value <= 0 means choose
     375                 :         // automatically based on the DPI. A positive value is used as-is. This effectively
     376                 :         // controls the size of a CSS "px".
     377               0 :         float devPixelsPerCSSPixel = -1.0;
     378                 : 
     379               0 :         nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
     380               0 :         if (!prefString.IsEmpty()) {
     381               0 :             devPixelsPerCSSPixel = static_cast<float>(atof(prefString));
     382                 :         }
     383                 : 
     384               0 :         if (devPixelsPerCSSPixel <= 0) {
     385               0 :             if (mWidget) {
     386               0 :                 devPixelsPerCSSPixel = mWidget->GetDefaultScale();
     387                 :             } else {
     388               0 :                 devPixelsPerCSSPixel = 1.0;
     389                 :             }
     390                 :         }
     391                 : 
     392                 :         mAppUnitsPerDevNotScaledPixel =
     393               0 :             NS_MAX(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
     394                 :     }
     395                 : 
     396               0 :     NS_ASSERTION(dpi != -1.0, "no dpi set");
     397                 : 
     398               0 :     mAppUnitsPerPhysicalInch = NS_lround(dpi * mAppUnitsPerDevNotScaledPixel);
     399               0 :     UpdateScaledAppUnits();
     400               0 : }
     401                 : 
     402                 : nsresult
     403               0 : nsDeviceContext::Init(nsIWidget *aWidget)
     404                 : {
     405               0 :     if (mScreenManager && mWidget == aWidget)
     406               0 :         return NS_OK;
     407                 : 
     408               0 :     mWidget = aWidget;
     409               0 :     SetDPI();
     410                 : 
     411               0 :     if (mScreenManager)
     412               0 :         return NS_OK;
     413                 : 
     414               0 :     mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
     415                 : 
     416               0 :     return NS_OK;
     417                 : }
     418                 : 
     419                 : nsresult
     420               0 : nsDeviceContext::CreateRenderingContext(nsRenderingContext *&aContext)
     421                 : {
     422               0 :     NS_ABORT_IF_FALSE(mPrintingSurface, "only call for printing dcs");
     423                 : 
     424               0 :     nsRefPtr<nsRenderingContext> pContext = new nsRenderingContext();
     425                 : 
     426               0 :     pContext->Init(this, mPrintingSurface);
     427               0 :     pContext->Scale(mPrintingScale, mPrintingScale);
     428               0 :     aContext = pContext;
     429               0 :     NS_ADDREF(aContext);
     430                 : 
     431               0 :     return NS_OK;
     432                 : }
     433                 : 
     434                 : nsresult
     435               0 : nsDeviceContext::GetDepth(PRUint32& aDepth)
     436                 : {
     437               0 :     if (mDepth == 0) {
     438               0 :         nsCOMPtr<nsIScreen> primaryScreen;
     439               0 :         mScreenManager->GetPrimaryScreen(getter_AddRefs(primaryScreen));
     440               0 :         primaryScreen->GetColorDepth(reinterpret_cast<PRInt32 *>(&mDepth));
     441                 :     }
     442                 : 
     443               0 :     aDepth = mDepth;
     444               0 :     return NS_OK;
     445                 : }
     446                 : 
     447                 : nsresult
     448               0 : nsDeviceContext::GetDeviceSurfaceDimensions(nscoord &aWidth, nscoord &aHeight)
     449                 : {
     450               0 :     if (mPrintingSurface) {
     451                 :         // we have a printer device
     452               0 :         aWidth = mWidth;
     453               0 :         aHeight = mHeight;
     454                 :     } else {
     455               0 :         nsRect area;
     456               0 :         ComputeFullAreaUsingScreen(&area);
     457               0 :         aWidth = area.width;
     458               0 :         aHeight = area.height;
     459                 :     }
     460                 : 
     461               0 :     return NS_OK;
     462                 : }
     463                 : 
     464                 : nsresult
     465               0 : nsDeviceContext::GetRect(nsRect &aRect)
     466                 : {
     467               0 :     if (mPrintingSurface) {
     468                 :         // we have a printer device
     469               0 :         aRect.x = 0;
     470               0 :         aRect.y = 0;
     471               0 :         aRect.width = mWidth;
     472               0 :         aRect.height = mHeight;
     473                 :     } else
     474               0 :         ComputeFullAreaUsingScreen ( &aRect );
     475                 : 
     476               0 :     return NS_OK;
     477                 : }
     478                 : 
     479                 : nsresult
     480               0 : nsDeviceContext::GetClientRect(nsRect &aRect)
     481                 : {
     482               0 :     if (mPrintingSurface) {
     483                 :         // we have a printer device
     484               0 :         aRect.x = 0;
     485               0 :         aRect.y = 0;
     486               0 :         aRect.width = mWidth;
     487               0 :         aRect.height = mHeight;
     488                 :     }
     489                 :     else
     490               0 :         ComputeClientRectUsingScreen(&aRect);
     491                 : 
     492               0 :     return NS_OK;
     493                 : }
     494                 : 
     495                 : nsresult
     496               0 : nsDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice)
     497                 : {
     498               0 :     NS_ENSURE_ARG_POINTER(aDevice);
     499                 : 
     500               0 :     mDeviceContextSpec = aDevice;
     501                 : 
     502               0 :     nsresult rv = aDevice->GetSurfaceForPrinter(getter_AddRefs(mPrintingSurface));
     503               0 :     if (NS_FAILED(rv))
     504               0 :         return NS_ERROR_FAILURE;
     505                 : 
     506               0 :     Init(nsnull);
     507                 : 
     508               0 :     CalcPrintingSize();
     509                 : 
     510               0 :     return NS_OK;
     511                 : }
     512                 : 
     513                 : nsresult
     514               0 : nsDeviceContext::BeginDocument(PRUnichar*  aTitle,
     515                 :                                PRUnichar*  aPrintToFileName,
     516                 :                                PRInt32     aStartPage,
     517                 :                                PRInt32     aEndPage)
     518                 : {
     519                 :     static const PRUnichar kEmpty[] = { '\0' };
     520                 :     nsresult rv;
     521                 : 
     522               0 :     rv = mPrintingSurface->BeginPrinting(nsDependentString(aTitle ? aTitle : kEmpty),
     523               0 :                                          nsDependentString(aPrintToFileName ? aPrintToFileName : kEmpty));
     524                 : 
     525               0 :     if (NS_SUCCEEDED(rv) && mDeviceContextSpec)
     526               0 :         rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName, aStartPage, aEndPage);
     527                 : 
     528               0 :     return rv;
     529                 : }
     530                 : 
     531                 : 
     532                 : nsresult
     533               0 : nsDeviceContext::EndDocument(void)
     534                 : {
     535               0 :     nsresult rv = NS_OK;
     536                 : 
     537               0 :     if (mPrintingSurface) {
     538               0 :         rv = mPrintingSurface->EndPrinting();
     539               0 :         if (NS_SUCCEEDED(rv))
     540               0 :             mPrintingSurface->Finish();
     541                 :     }
     542                 : 
     543               0 :     if (mDeviceContextSpec)
     544               0 :         mDeviceContextSpec->EndDocument();
     545                 : 
     546               0 :     return rv;
     547                 : }
     548                 : 
     549                 : 
     550                 : nsresult
     551               0 : nsDeviceContext::AbortDocument(void)
     552                 : {
     553               0 :     nsresult rv = mPrintingSurface->AbortPrinting();
     554                 : 
     555               0 :     if (mDeviceContextSpec)
     556               0 :         mDeviceContextSpec->EndDocument();
     557                 : 
     558               0 :     return rv;
     559                 : }
     560                 : 
     561                 : 
     562                 : nsresult
     563               0 : nsDeviceContext::BeginPage(void)
     564                 : {
     565               0 :     nsresult rv = NS_OK;
     566                 : 
     567               0 :     if (mDeviceContextSpec)
     568               0 :         rv = mDeviceContextSpec->BeginPage();
     569                 : 
     570               0 :     if (NS_FAILED(rv)) return rv;
     571                 : 
     572                 : #ifdef XP_MACOSX
     573                 :     // We need to get a new surface for each page on the Mac, as the
     574                 :     // CGContextRefs are only good for one page.
     575                 :     // And we don't null it out in EndPage because mPrintingSurface needs
     576                 :     // to be available also in-between EndPage/BeginPage (bug 665218).
     577                 :     mDeviceContextSpec->GetSurfaceForPrinter(getter_AddRefs(mPrintingSurface));
     578                 : #endif
     579                 : 
     580               0 :     rv = mPrintingSurface->BeginPage();
     581                 : 
     582               0 :     return rv;
     583                 : }
     584                 : 
     585                 : nsresult
     586               0 : nsDeviceContext::EndPage(void)
     587                 : {
     588               0 :     nsresult rv = mPrintingSurface->EndPage();
     589                 : 
     590               0 :     if (mDeviceContextSpec)
     591               0 :         mDeviceContextSpec->EndPage();
     592                 : 
     593               0 :     return rv;
     594                 : }
     595                 : 
     596                 : void
     597               0 : nsDeviceContext::ComputeClientRectUsingScreen(nsRect* outRect)
     598                 : {
     599                 :     // we always need to recompute the clientRect
     600                 :     // because the window may have moved onto a different screen. In the single
     601                 :     // monitor case, we only need to do the computation if we haven't done it
     602                 :     // once already, and remember that we have because we're assured it won't change.
     603               0 :     nsCOMPtr<nsIScreen> screen;
     604               0 :     FindScreen (getter_AddRefs(screen));
     605               0 :     if (screen) {
     606                 :         PRInt32 x, y, width, height;
     607               0 :         screen->GetAvailRect(&x, &y, &width, &height);
     608                 : 
     609                 :         // convert to device units
     610               0 :         outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
     611               0 :         outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
     612               0 :         outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
     613               0 :         outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
     614                 :     }
     615               0 : }
     616                 : 
     617                 : void
     618               0 : nsDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
     619                 : {
     620                 :     // if we have more than one screen, we always need to recompute the clientRect
     621                 :     // because the window may have moved onto a different screen. In the single
     622                 :     // monitor case, we only need to do the computation if we haven't done it
     623                 :     // once already, and remember that we have because we're assured it won't change.
     624               0 :     nsCOMPtr<nsIScreen> screen;
     625               0 :     FindScreen ( getter_AddRefs(screen) );
     626               0 :     if ( screen ) {
     627                 :         PRInt32 x, y, width, height;
     628               0 :         screen->GetRect ( &x, &y, &width, &height );
     629                 : 
     630                 :         // convert to device units
     631               0 :         outRect->y = NSIntPixelsToAppUnits(y, AppUnitsPerDevPixel());
     632               0 :         outRect->x = NSIntPixelsToAppUnits(x, AppUnitsPerDevPixel());
     633               0 :         outRect->width = NSIntPixelsToAppUnits(width, AppUnitsPerDevPixel());
     634               0 :         outRect->height = NSIntPixelsToAppUnits(height, AppUnitsPerDevPixel());
     635                 : 
     636               0 :         mWidth = outRect->width;
     637               0 :         mHeight = outRect->height;
     638                 :     }
     639               0 : }
     640                 : 
     641                 : //
     642                 : // FindScreen
     643                 : //
     644                 : // Determines which screen intersects the largest area of the given surface.
     645                 : //
     646                 : void
     647               0 : nsDeviceContext::FindScreen(nsIScreen** outScreen)
     648                 : {
     649               0 :     if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW))
     650               0 :         mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW),
     651               0 :                                               outScreen);
     652                 :     else
     653               0 :         mScreenManager->GetPrimaryScreen(outScreen);
     654               0 : }
     655                 : 
     656                 : void
     657               0 : nsDeviceContext::CalcPrintingSize()
     658                 : {
     659               0 :     if (!mPrintingSurface)
     660               0 :         return;
     661                 : 
     662               0 :     bool inPoints = true;
     663                 : 
     664               0 :     gfxSize size(0, 0);
     665               0 :     switch (mPrintingSurface->GetType()) {
     666                 :     case gfxASurface::SurfaceTypeImage:
     667               0 :         inPoints = false;
     668               0 :         size = reinterpret_cast<gfxImageSurface*>(mPrintingSurface.get())->GetSize();
     669               0 :         break;
     670                 : 
     671                 : #if defined(MOZ_PDF_PRINTING)
     672                 :     case gfxASurface::SurfaceTypePDF:
     673               0 :         inPoints = true;
     674               0 :         size = reinterpret_cast<gfxPDFSurface*>(mPrintingSurface.get())->GetSize();
     675               0 :         break;
     676                 : #endif
     677                 : 
     678                 : #ifdef MOZ_ENABLE_GTK2
     679                 :     case gfxASurface::SurfaceTypePS:
     680               0 :         inPoints = true;
     681               0 :         size = reinterpret_cast<gfxPSSurface*>(mPrintingSurface.get())->GetSize();
     682               0 :         break;
     683                 : #endif
     684                 : 
     685                 : #ifdef XP_MACOSX
     686                 :     case gfxASurface::SurfaceTypeQuartz:
     687                 :         inPoints = true; // this is really only true when we're printing
     688                 :         size = reinterpret_cast<gfxQuartzSurface*>(mPrintingSurface.get())->GetSize();
     689                 :         break;
     690                 : #endif
     691                 : 
     692                 : #ifdef XP_WIN
     693                 :     case gfxASurface::SurfaceTypeWin32:
     694                 :     case gfxASurface::SurfaceTypeWin32Printing:
     695                 :         {
     696                 :             inPoints = false;
     697                 :             HDC dc = reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
     698                 :             if (!dc)
     699                 :                 dc = GetDC((HWND)mWidget->GetNativeData(NS_NATIVE_WIDGET));
     700                 :             size.width = NSFloatPixelsToAppUnits(::GetDeviceCaps(dc, HORZRES)/mPrintingScale, AppUnitsPerDevPixel());
     701                 :             size.height = NSFloatPixelsToAppUnits(::GetDeviceCaps(dc, VERTRES)/mPrintingScale, AppUnitsPerDevPixel());
     702                 :             mDepth = (PRUint32)::GetDeviceCaps(dc, BITSPIXEL);
     703                 :             if (dc != reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC())
     704                 :                 ReleaseDC((HWND)mWidget->GetNativeData(NS_NATIVE_WIDGET), dc);
     705                 :             break;
     706                 :         }
     707                 : #endif
     708                 : 
     709                 : #ifdef XP_OS2
     710                 :     case gfxASurface::SurfaceTypeOS2:
     711                 :         {
     712                 :             inPoints = false;
     713                 :             // we already set the size in the surface constructor we set for
     714                 :             // printing, so just get those values here
     715                 :             size = reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetSize();
     716                 :             // as they are in pixels we need to scale them to app units
     717                 :             size.width = NSFloatPixelsToAppUnits(size.width, AppUnitsPerDevPixel());
     718                 :             size.height = NSFloatPixelsToAppUnits(size.height, AppUnitsPerDevPixel());
     719                 :             // still need to get the depth from the device context
     720                 :             HDC dc = GpiQueryDevice(reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetPS());
     721                 :             LONG value;
     722                 :             if (DevQueryCaps(dc, CAPS_COLOR_BITCOUNT, 1, &value))
     723                 :                 mDepth = value;
     724                 :             else
     725                 :                 mDepth = 8; // default to 8bpp, should be enough for printers
     726                 :             break;
     727                 :         }
     728                 : #endif
     729                 :     default:
     730               0 :         NS_ERROR("trying to print to unknown surface type");
     731                 :     }
     732                 : 
     733               0 :     if (inPoints) {
     734                 :         // For printing, CSS inches and physical inches are identical
     735                 :         // so it doesn't matter which we use here
     736               0 :         mWidth = NSToCoordRound(float(size.width) * AppUnitsPerPhysicalInch() / 72);
     737               0 :         mHeight = NSToCoordRound(float(size.height) * AppUnitsPerPhysicalInch() / 72);
     738                 :     } else {
     739               0 :         mWidth = NSToIntRound(size.width);
     740               0 :         mHeight = NSToIntRound(size.height);
     741                 :     }
     742                 : }
     743                 : 
     744               0 : bool nsDeviceContext::CheckDPIChange() {
     745               0 :     PRInt32 oldDevPixels = mAppUnitsPerDevNotScaledPixel;
     746               0 :     PRInt32 oldInches = mAppUnitsPerPhysicalInch;
     747                 : 
     748               0 :     SetDPI();
     749                 : 
     750                 :     return oldDevPixels != mAppUnitsPerDevNotScaledPixel ||
     751               0 :         oldInches != mAppUnitsPerPhysicalInch;
     752                 : }
     753                 : 
     754                 : bool
     755               0 : nsDeviceContext::SetPixelScale(float aScale)
     756                 : {
     757               0 :     if (aScale <= 0) {
     758               0 :         NS_NOTREACHED("Invalid pixel scale value");
     759               0 :         return false;
     760                 :     }
     761               0 :     PRUint32 oldAppUnitsPerDevPixel = mAppUnitsPerDevPixel;
     762               0 :     mPixelScale = aScale;
     763               0 :     UpdateScaledAppUnits();
     764               0 :     return oldAppUnitsPerDevPixel != mAppUnitsPerDevPixel;
     765                 : }
     766                 : 
     767                 : void
     768               0 : nsDeviceContext::UpdateScaledAppUnits()
     769                 : {
     770                 :     mAppUnitsPerDevPixel =
     771               0 :         NS_MAX(1, NSToIntRound(float(mAppUnitsPerDevNotScaledPixel) / mPixelScale));
     772               0 : }

Generated by: LCOV version 1.7