From b2cad6ca8d94c3a9ef18069ff5c157607c36cc52 Mon Sep 17 00:00:00 2001 From: "sharparrow1%yahoo.com" Date: Thu, 15 Feb 2007 09:04:25 +0000 Subject: [PATCH] Bug 369698: fix dynamic changes to layout.css.dpi pref. r+sr=roc. --- gfx/public/nsIDeviceContext.h | 7 ++ gfx/src/thebes/nsThebesDeviceContext.cpp | 108 +++++++++-------------- gfx/src/thebes/nsThebesDeviceContext.h | 8 +- layout/base/nsPresContext.cpp | 22 +++++ 4 files changed, 74 insertions(+), 71 deletions(-) diff --git a/gfx/public/nsIDeviceContext.h b/gfx/public/nsIDeviceContext.h index b2c2d9d0469..9aa867cdaab 100644 --- a/gfx/public/nsIDeviceContext.h +++ b/gfx/public/nsIDeviceContext.h @@ -477,6 +477,13 @@ public: */ NS_IMETHOD ClearCachedSystemFonts() = 0; + /** + * Check to see if the DPI has changed + * @return whether there was actually a change in the DPI + * (whether AppUnitsPerDevPixel() or AppUnitsPerInch() changed) + */ + virtual PRBool CheckDPIChange() = 0; + protected: PRInt32 mAppUnitsPerDevPixel; PRInt32 mAppUnitsPerInch; diff --git a/gfx/src/thebes/nsThebesDeviceContext.cpp b/gfx/src/thebes/nsThebesDeviceContext.cpp index 0220011ce30..8e71b31b541 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.cpp +++ b/gfx/src/thebes/nsThebesDeviceContext.cpp @@ -131,36 +131,38 @@ nsThebesDeviceContext::nsThebesDeviceContext() nsThebesDeviceContext::~nsThebesDeviceContext() { - nsresult rv; - nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - prefs->UnregisterCallback("layout.css.dpi", - prefChanged, (void *)this); - } } nsresult -nsThebesDeviceContext::SetDPI(PRInt32 aPrefDPI) +nsThebesDeviceContext::SetDPI() { PRInt32 dpi = 96; + // Set prefVal the value of the preference + // "layout.css.dpi" + // or -1 if we can't get it. + // If it's negative, we pretend it's not set. + // If it's 0, it means force use of the operating system's logical + // resolution. + // If it's positive, we use it as the logical resolution + nsresult rv; + PRInt32 prefDPI; + nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv) && prefs) { + rv = prefs->GetIntPref("layout.css.dpi", &prefDPI); + if (NS_FAILED(rv)) { + prefDPI = -1; + } + } + #if defined(MOZ_ENABLE_GTK2) float screenWidthIn = float(::gdk_screen_width_mm()) / 25.4f; PRInt32 OSVal = NSToCoordRound(float(::gdk_screen_width()) / screenWidthIn); - if (aPrefDPI > 0) { - // If there's a valid pref value for the logical resolution, - // use it. - dpi = aPrefDPI; - } else if ((aPrefDPI == 0) || (OSVal > 96)) { - // Either if the pref is 0 (force use of OS value) or the OS - // value is bigger than 96, use the OS value. + if (prefDPI == 0) // Force the use of the OS dpi dpi = OSVal; - } else { - // if we couldn't get the pref or it's negative, and the OS - // value is under 96ppi, then use 96. - dpi = 96; - } + else // Otherwise, the minimum dpi is 96dpi + dpi = PR_MAX(OSVal, 96); if (mPrinter) { // cairo printing doesn't really have the @@ -183,14 +185,16 @@ nsThebesDeviceContext::SetDPI(PRInt32 aPrefDPI) #elif defined(XP_MACOSX) + // XXX Need to get the screen DPI instead of defaulting to 96dpi + if (mPrinter) { dpi = 72; } #endif - if (aPrefDPI > 0 && !mPrinter) - dpi = aPrefDPI; + if (prefDPI > 0 && !mPrinter) + dpi = prefDPI; mAppUnitsPerDevPixel = AppUnitsPerCSSPixel() / PR_MAX(1, (dpi + 48) / 96); mAppUnitsPerInch = NSIntPixelsToAppUnits(dpi, mAppUnitsPerDevPixel); @@ -203,28 +207,7 @@ nsThebesDeviceContext::Init(nsNativeWidget aWidget) { mWidget = aWidget; - PRInt32 prefVal = -1; - - // Set prefVal the value of the preference - // "layout.css.dpi" - // or -1 if we can't get it. - // If it's negative, we pretend it's not set. - // If it's 0, it means force use of the operating system's logical - // resolution. - // If it's positive, we use it as the logical resolution - nsresult res; - - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &res)); - if (NS_SUCCEEDED(res) && prefs) { - res = prefs->GetIntPref("layout.css.dpi", &prefVal); - if (NS_FAILED(res)) { - prefVal = -1; - } - prefs->RegisterCallback("layout.css.dpi", prefChanged, - (void *)this); - } - - SetDPI(prefVal); + SetDPI(); #ifdef MOZ_ENABLE_GTK2 @@ -445,8 +428,8 @@ nsThebesDeviceContext::GetRect(nsRect &aRect) // we have a printer device aRect.x = 0; aRect.y = 0; - aRect.width = NSToIntRound(mWidth); - aRect.height = NSToIntRound(mHeight); + aRect.width = mWidth; + aRect.height = mHeight; } else ComputeFullAreaUsingScreen ( &aRect ); @@ -460,8 +443,8 @@ nsThebesDeviceContext::GetClientRect(nsRect &aRect) // we have a printer device aRect.x = 0; aRect.y = 0; - aRect.width = NSToIntRound(mWidth); - aRect.height = NSToIntRound(mHeight); + aRect.width = mWidth; + aRect.height = mHeight; } else ComputeClientRectUsingScreen(&aRect); @@ -586,24 +569,6 @@ nsThebesDeviceContext::EndPage(void) /** End printing methods **/ -int -nsThebesDeviceContext::prefChanged(const char *aPref, void *aClosure) -{ - nsThebesDeviceContext *context = (nsThebesDeviceContext*)aClosure; - nsresult rv; - - if (nsCRT::strcmp(aPref, "layout.css.dpi") == 0) { - PRInt32 dpi; - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &rv)); - rv = prefs->GetIntPref(aPref, &dpi); - if (NS_SUCCEEDED(rv)) - context->SetDPI(dpi); - } - - return 0; -} - - void nsThebesDeviceContext::ComputeClientRectUsingScreen(nsRect* outRect) { @@ -716,8 +681,8 @@ nsThebesDeviceContext::CalcPrintingSize() } if (inPoints) { - mWidth = float(size.width) * AppUnitsPerInch() / 72; - mHeight = float(size.height) * AppUnitsPerInch() / 72; + mWidth = NSToCoordRound(float(size.width) * AppUnitsPerInch() / 72); + mHeight = NSToCoordRound(float(size.height) * AppUnitsPerInch() / 72); printf("%f %f\n", size.width, size.height); printf("%d %d\n", (PRInt32)mWidth, (PRInt32)mHeight); } else { @@ -726,3 +691,12 @@ nsThebesDeviceContext::CalcPrintingSize() } } +PRBool nsThebesDeviceContext::CheckDPIChange() { + PRInt32 oldDevPixels = mAppUnitsPerDevPixel; + PRInt32 oldInches = mAppUnitsPerInch; + + SetDPI(); + + return oldDevPixels != mAppUnitsPerDevPixel || + oldInches != mAppUnitsPerInch; +} diff --git a/gfx/src/thebes/nsThebesDeviceContext.h b/gfx/src/thebes/nsThebesDeviceContext.h index a87c510f253..d8aa2bf644e 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.h +++ b/gfx/src/thebes/nsThebesDeviceContext.h @@ -112,7 +112,7 @@ public: static void DebugShowCairoSurface (const char *aName, cairo_surface_t *aSurface); - static int prefChanged(const char *aPref, void *aClosure); + virtual PRBool CheckDPIChange(); nsNativeWidget GetWidget() { return mWidget; } #ifdef XP_WIN @@ -126,7 +126,7 @@ public: #endif protected: - nsresult SetDPI(PRInt32 aPrefDPI); + nsresult SetDPI(); void ComputeClientRectUsingScreen(nsRect* outRect); void ComputeFullAreaUsingScreen(nsRect* outRect); void FindScreen(nsIScreen** outScreen); @@ -137,8 +137,8 @@ protected: private: nsCOMPtr mScreenManager; - PRInt32 mWidth; - PRInt32 mHeight; + nscoord mWidth; + nscoord mHeight; PRBool mPrinter; nsRefPtrHashtable mWidgetSurfaceCache; diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index f6b664b7695..67d47e53654 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -76,6 +76,7 @@ #include "nsThreadUtils.h" #include "nsFrameManager.h" #include "nsLayoutUtils.h" +#include "nsIViewManager.h" #ifdef IBMBIDI #include "nsBidiPresUtils.h" @@ -273,6 +274,9 @@ nsPresContext::~nsPresContext() delete mBidiUtils; #endif // IBMBIDI + nsContentUtils::UnregisterPrefCallback("layout.css.dpi", + nsPresContext::PrefChangedCallback, + this); NS_IF_RELEASE(mDeviceContext); NS_IF_RELEASE(mLookAndFeel); @@ -654,6 +658,21 @@ nsPresContext::ClearStyleDataAndReflow() void nsPresContext::PreferenceChanged(const char* aPrefName) { + if (!nsCRT::strcmp(aPrefName, "layout.css.dpi")) { + nsRect bounds(mVisibleArea); + bounds *= 1.0f / AppUnitsPerDevPixel(); + if (mDeviceContext->CheckDPIChange() && mShell) { + mDeviceContext->FlushFontCache(); + + nsIViewManager* vm = GetViewManager(); + nscoord width = DevPixelsToAppUnits(bounds.width); + nscoord height = DevPixelsToAppUnits(bounds.height); + vm->SetWindowDimensions(width, height); + + ClearStyleDataAndReflow(); + } + return; + } // we use a zero-delay timer to coalesce multiple pref updates if (!mPrefChangedTimer) { @@ -743,6 +762,9 @@ nsPresContext::Init(nsIDeviceContext* aDeviceContext) nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback, this); #endif + nsContentUtils::RegisterPrefCallback("layout.css.dpi", + nsPresContext::PrefChangedCallback, + this); rv = mEventManager->Init(); NS_ENSURE_SUCCESS(rv, rv);