Bug 4821: Implement page zoom (backend). r+sr=roc.
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -130,22 +130,23 @@ nsPoint nsDOMUIEvent::GetScreenPoint() {
mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
!NS_IS_DRAG_EVENT(mEvent))) {
return nsPoint(0, 0);
}
if (!((nsGUIEvent*)mEvent)->widget ) {
return mEvent->refPoint;
}
-
+
nsRect bounds(mEvent->refPoint, nsSize(1, 1));
nsRect offset;
((nsGUIEvent*)mEvent)->widget->WidgetToScreen ( bounds, offset );
- return nsPoint(nsPresContext::AppUnitsToIntCSSPixels(mPresContext->DevPixelsToAppUnits(offset.x)),
- nsPresContext::AppUnitsToIntCSSPixels(mPresContext->DevPixelsToAppUnits(offset.y)));
+ PRInt32 factor = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
+ return nsPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
+ nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
}
nsPoint nsDOMUIEvent::GetClientPoint() {
if (!mEvent ||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
mEvent->eventStructType != NS_POPUP_EVENT &&
mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
!NS_IS_DRAG_EVENT(mEvent)) ||
--- a/docshell/base/nsIMarkupDocumentViewer.idl
+++ b/docshell/base/nsIMarkupDocumentViewer.idl
@@ -59,16 +59,19 @@ interface nsIMarkupDocumentViewer : nsIS
/*
Scrolls to a given DOM content node.
*/
void scrollToNode(in nsIDOMNode node);
/** The amount by which to scale all text. Default is 1.0. */
attribute float textZoom;
+ /** The amount by which to scale all lengths. Default is 1.0. */
+ attribute float fullZoom;
+
/** Disable entire author style level (including HTML presentation hints) */
attribute boolean authorStyleDisabled;
/*
XXX Comment here!
*/
attribute ACString defaultCharacterSet;
--- a/gfx/public/nsIDeviceContext.h
+++ b/gfx/public/nsIDeviceContext.h
@@ -460,16 +460,37 @@ public:
/**
* 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;
+ /**
+ * Set the pixel scaling factor: all lengths are multiplied by this factor
+ * when we convert them to device pixels. Returns whether the ratio of
+ * app units to dev pixels changed because of the scale factor.
+ */
+ virtual PRBool SetPixelScale(float aScale) = 0;
+
+ /**
+ * Get the pixel scaling factor; defaults to 1.0, but can be changed with
+ * SetPixelScale.
+ */
+ float GetPixelScale() const { return mPixelScale; }
+
+ /**
+ * Get the unscaled ratio of app units to dev pixels; useful if something
+ * needs to be converted from to unscaled pixels
+ */
+ PRInt32 UnscaledAppUnitsPerDevPixel() { return mAppUnitsPerDevNotScaledPixel; }
+
protected:
PRInt32 mAppUnitsPerDevPixel;
PRInt32 mAppUnitsPerInch;
+ PRInt32 mAppUnitsPerDevNotScaledPixel;
+ float mPixelScale;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDeviceContext, NS_IDEVICE_CONTEXT_IID)
#endif /* nsIDeviceContext_h___ */
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -52,16 +52,19 @@
#include "nsIRenderingContext.h"
NS_IMPL_ISUPPORTS3(DeviceContextImpl, nsIDeviceContext, nsIObserver, nsISupportsWeakReference)
DeviceContextImpl::DeviceContextImpl()
{
mAppUnitsPerDevPixel = -1;
mAppUnitsPerInch = -1;
+ mAppUnitsPerDevNotScaledPixel = -1;
+ mPixelScale = 1.0f;
+
mFontCache = nsnull;
mWidget = nsnull;
mFontAliasTable = nsnull;
#ifdef NS_DEBUG
mInitialized = PR_FALSE;
#endif
}
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -225,28 +225,30 @@ nsThebesDeviceContext::SetDPI()
NS_ASSERTION(dpi != -1, "no dpi set");
if (dotsArePixels) {
// First figure out the closest multiple of 96, which is the number of
// dev pixels per CSS pixel. Then, divide that into AppUnitsPerCSSPixel()
// to get the number of app units per dev pixel. The PR_MAXes are to
// make sure we don't end up dividing by zero.
- mAppUnitsPerDevPixel = PR_MAX(1, AppUnitsPerCSSPixel() /
- PR_MAX(1, (dpi + 48) / 96));
+ mAppUnitsPerDevNotScaledPixel = PR_MAX(1, AppUnitsPerCSSPixel() /
+ PR_MAX(1, (dpi + 48) / 96));
} else {
/* set mAppUnitsPerDevPixel so we're using exactly 72 dpi, even
* though that means we have a non-integer number of device "pixels"
* per CSS pixel
*/
- mAppUnitsPerDevPixel = (AppUnitsPerCSSPixel() * 96) / dpi;
+ mAppUnitsPerDevNotScaledPixel = (AppUnitsPerCSSPixel() * 96) / dpi;
}
- mAppUnitsPerInch = NSIntPixelsToAppUnits(dpi, mAppUnitsPerDevPixel);
+ mAppUnitsPerInch = NSIntPixelsToAppUnits(dpi, mAppUnitsPerDevNotScaledPixel);
+
+ UpdateScaledAppUnits();
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::Init(nsNativeWidget aWidget)
{
mWidget = aWidget;
@@ -722,16 +724,35 @@ nsThebesDeviceContext::CalcPrintingSize(
printf("%d %d\n", (PRInt32)mWidth, (PRInt32)mHeight);
} else {
mWidth = NSToIntRound(size.width);
mHeight = NSToIntRound(size.height);
}
}
PRBool nsThebesDeviceContext::CheckDPIChange() {
- PRInt32 oldDevPixels = mAppUnitsPerDevPixel;
+ PRInt32 oldDevPixels = mAppUnitsPerDevNotScaledPixel;
PRInt32 oldInches = mAppUnitsPerInch;
SetDPI();
- return oldDevPixels != mAppUnitsPerDevPixel ||
+ return oldDevPixels != mAppUnitsPerDevNotScaledPixel ||
oldInches != mAppUnitsPerInch;
}
+
+PRBool
+nsThebesDeviceContext::SetPixelScale(float aScale)
+{
+ if (aScale <= 0) {
+ NS_NOTREACHED("Invalid pixel scale value");
+ return PR_FALSE;
+ }
+ PRInt32 oldAppUnitsPerDevPixel = mAppUnitsPerDevPixel;
+ mPixelScale = aScale;
+ UpdateScaledAppUnits();
+ return oldAppUnitsPerDevPixel != mAppUnitsPerDevPixel;
+}
+
+void
+nsThebesDeviceContext::UpdateScaledAppUnits()
+{
+ mAppUnitsPerDevPixel = PR_MAX(1, PRInt32(float(mAppUnitsPerDevNotScaledPixel) / mPixelScale));
+}
--- a/gfx/src/thebes/nsThebesDeviceContext.h
+++ b/gfx/src/thebes/nsThebesDeviceContext.h
@@ -111,16 +111,18 @@ public:
NS_IMETHOD BeginPage(void);
NS_IMETHOD EndPage(void);
/* end printing goop */
static void DebugShowCairoSurface (const char *aName, cairo_surface_t *aSurface);
virtual PRBool CheckDPIChange();
+ virtual PRBool SetPixelScale(float aScale);
+
nsNativeWidget GetWidget() { return mWidget; }
#ifdef XP_WIN
HDC GetPrintHDC() {
if (mPrintingSurface) {
NS_ASSERTION(mPrintingSurface->GetType() == gfxASurface::SurfaceTypeWin32, "invalid surface type");
return reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
}
return nsnull;
@@ -137,16 +139,17 @@ public:
#endif
protected:
nsresult SetDPI();
void ComputeClientRectUsingScreen(nsRect *outRect);
void ComputeFullAreaUsingScreen(nsRect *outRect);
void FindScreen(nsIScreen **outScreen);
void CalcPrintingSize();
+ void UpdateScaledAppUnits();
PRUint32 mDepth;
private:
nsCOMPtr<nsIScreenManager> mScreenManager;
nscoord mWidth;
nscoord mHeight;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2567,16 +2567,34 @@ DocumentViewerImpl::GetTextZoom(float* a
NS_ENSURE_ARG_POINTER(aTextZoom);
NS_ASSERTION(!mPresContext || mPresContext->TextZoom() == mTextZoom,
"mPresContext->TextZoom() != mTextZoom");
*aTextZoom = mTextZoom;
return NS_OK;
}
+NS_IMETHODIMP
+DocumentViewerImpl::SetFullZoom(float aFullZoom)
+{
+ if (mPresContext) {
+ mPresContext->SetFullZoom(aFullZoom);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+DocumentViewerImpl::GetFullZoom(float* aFullZoom)
+{
+ NS_ENSURE_ARG_POINTER(aFullZoom);
+ *aFullZoom = mPresContext ? mPresContext->GetFullZoom() : 1.0;
+ return NS_OK;
+}
+
static void
SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer* aChild, void* aClosure)
{
PRBool styleDisabled = *static_cast<PRBool*>(aClosure);
aChild->SetAuthorStyleDisabled(styleDisabled);
}
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1068,19 +1068,33 @@ nsPresContext::GetDefaultFontInternal(PR
const nsFont*
nsPresContext::GetDefaultFontExternal(PRUint8 aFontID) const
{
return GetDefaultFontInternal(aFontID);
}
void
-nsPresContext::SetTextZoomExternal(float aZoom)
+nsPresContext::SetFullZoom(float aZoom)
{
- SetTextZoomInternal(aZoom);
+ nsPresContext* rootPresContext = RootPresContext();
+ if (rootPresContext != this) {
+ NS_WARNING("Zoom set on non-root prescontext");
+ rootPresContext->SetFullZoom(aZoom);
+ return;
+ }
+ nsRect bounds(mVisibleArea);
+ bounds.ScaleRoundPreservingCentersInverse(AppUnitsPerDevPixel());
+ if (!mShell || !mDeviceContext->SetPixelScale(aZoom))
+ return;
+ mDeviceContext->FlushFontCache();
+ nscoord width = DevPixelsToAppUnits(bounds.width);
+ nscoord height = DevPixelsToAppUnits(bounds.height);
+ GetViewManager()->SetWindowDimensions(width, height);
+ ClearStyleDataAndReflow();
}
imgIRequest*
nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
{
// look and see if we have a loader for the target frame.
nsCOMPtr<nsImageLoader> loader;
mImageLoaders.Get(aTargetFrame, getter_AddRefs(loader));
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -457,26 +457,23 @@ public:
float GetPrintPreviewScale() { return mPPScale; }
void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
nsIDeviceContext* DeviceContext() { return mDeviceContext; }
nsIEventStateManager* EventStateManager() { return mEventManager; }
nsIAtom* GetLangGroup() { return mLangGroup; }
float TextZoom() { return mTextZoom; }
- void SetTextZoomInternal(float aZoom) {
+ void SetTextZoom(float aZoom) {
mTextZoom = aZoom;
ClearStyleDataAndReflow();
}
- virtual NS_HIDDEN_(void) SetTextZoomExternal(float aZoom);
-#ifdef _IMPL_NS_LAYOUT
- void SetTextZoom(float aZoom) { SetTextZoomInternal(aZoom); }
-#else
- void SetTextZoom(float aZoom) { SetTextZoomExternal(aZoom); }
-#endif
+
+ float GetFullZoom() {return mDeviceContext->GetPixelScale();}
+ void SetFullZoom(float aZoom);
static PRInt32 AppUnitsPerCSSPixel() { return nsIDeviceContext::AppUnitsPerCSSPixel(); }
PRInt32 AppUnitsPerDevPixel() const { return mDeviceContext->AppUnitsPerDevPixel(); }
PRInt32 AppUnitsPerInch() const { return mDeviceContext->AppUnitsPerInch(); }
static nscoord CSSPixelsToAppUnits(PRInt32 aPixels)
{ return NSIntPixelsToAppUnits(aPixels,
nsIDeviceContext::AppUnitsPerCSSPixel()); }