From 74eea248f25c6c32f35c1c06695ea99d746b1341 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 3 Sep 2010 15:10:46 -0500 Subject: [PATCH] Bug 590294, part 9: Add API to set a expectation of the content window's viewport, and to draw content pixels in the at particular scale factors. sr=smaug --- content/base/public/nsIFrameLoader.idl | 32 +++++++++++- content/base/src/nsFrameLoader.cpp | 71 ++++++++++++++++++++++++++ content/base/src/nsFrameLoader.h | 47 +++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/content/base/public/nsIFrameLoader.idl b/content/base/public/nsIFrameLoader.idl index d090fa23a996..8c9cce692fd4 100644 --- a/content/base/public/nsIFrameLoader.idl +++ b/content/base/public/nsIFrameLoader.idl @@ -46,7 +46,7 @@ interface nsIFrame; interface nsIChromeFrameMessageManager; interface nsIVariant; -[scriptable, uuid(65d2c9e2-852c-48cf-a95d-9b82f1273c15)] +[scriptable, uuid(afb86369-d183-4bc4-9fce-26cd314a4ac0)] interface nsIFrameLoader : nsISupports { /** @@ -127,6 +127,36 @@ interface nsIFrameLoader : nsISupports attribute boolean delayRemoteDialogs; + /** + * Implement viewport scrolling/scaling, used to support + * asynchronous re-paints of content pixels. These interfaces are + * only meaningful for . + * + * These interfaces do *not* scroll or scale the content document; + * instead they set a "goal" scroll/scale wrt the current content + * viewport. When the content document is painted, the viewport* + * attributes are used to set a compensating transform. If the + * metrics of the content document's current pixels don't match the + * viewport* config, the transform matrix may need to translate + * content pixels and/or perform a "fuzzy-scale" that doesn't + * re-rasterize fonts or intelligently resample images. + * + * The viewport* attrs are allowed to transform content pixels in + * such a way that the 's visible rect encloses pixels that + * the content document does not (yet) define. + * + * The viewport scroll values are in units of content-document CSS + * pixels. + * + * These APIs are designed to be used with nsIDOMWindowUtils + * setDisplayPort() and setResolution(). + */ + void scrollViewportTo(in float xPx, in float yPx); + void scrollViewportBy(in float dxPx, in float dyPx); + void setViewportScale(in float xScale, in float yScale); + + readonly attribute float viewportScrollX; + readonly attribute float viewportScrollY; }; native alreadyAddRefed_nsFrameLoader(already_AddRefed); diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 12a6f26cebb9..dacad7f04bca 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -1529,6 +1529,77 @@ nsFrameLoader::UpdateBaseWindowPositionAndSize(nsIFrame *aIFrame) return NS_OK; } +NS_IMETHODIMP +nsFrameLoader::ScrollViewportTo(float aXpx, float aYpx) +{ + ViewportConfig config(mViewportConfig); + config.mScrollOffset = nsPoint(nsPresContext::CSSPixelsToAppUnits(aXpx), + nsPresContext::CSSPixelsToAppUnits(aYpx)); + return UpdateViewportConfig(config); +} + +NS_IMETHODIMP +nsFrameLoader::ScrollViewportBy(float aDXpx, float aDYpx) +{ + ViewportConfig config(mViewportConfig); + config.mScrollOffset.MoveBy(nsPresContext::CSSPixelsToAppUnits(aDXpx), + nsPresContext::CSSPixelsToAppUnits(aDYpx)); + return UpdateViewportConfig(config); +} + +NS_IMETHODIMP +nsFrameLoader::SetViewportScale(float aXScale, float aYScale) +{ + ViewportConfig config(mViewportConfig); + config.mXScale = aXScale; + config.mYScale = aYScale; + return UpdateViewportConfig(config); +} + +NS_IMETHODIMP +nsFrameLoader::GetViewportScrollX(float* aViewportScrollX) +{ + *aViewportScrollX = + nsPresContext::AppUnitsToFloatCSSPixels(mViewportConfig.mScrollOffset.x); + return NS_OK; +} + +NS_IMETHODIMP +nsFrameLoader::GetViewportScrollY(float* aViewportScrollY) +{ + *aViewportScrollY = + nsPresContext::AppUnitsToFloatCSSPixels(mViewportConfig.mScrollOffset.y); + return NS_OK; +} + +nsresult +nsFrameLoader::UpdateViewportConfig(const ViewportConfig& aNewConfig) +{ + if (aNewConfig == mViewportConfig) { + return NS_OK; + } + mViewportConfig = aNewConfig; + + // Viewport changed. Try to locate our subdoc frame and invalidate + // it if found. + nsIFrame* frame = GetPrimaryFrameOfOwningContent(); + if (!frame) { + // XXX should this be a silent failure? + return NS_ERROR_NOT_AVAILABLE; + } + + // XXX could be clever here and compute a smaller invalidation + // rect + nsRect rect = nsRect(nsPoint(0, 0), frame->GetRect().Size()); + // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep viewport + // semantics the same for both in-process and out-of-process + // . This is just a transform of the layer subtree in + // both. + frame->InvalidateWithFlags(rect, nsIFrame::INVALIDATE_NO_THEBES_LAYERS); + + return NS_OK; +} + nsIntSize nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame) { diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index e01ab75ab9f5..42ae749b3a0e 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -47,6 +47,7 @@ #include "nsIDocShell.h" #include "nsStringFwd.h" #include "nsIFrameLoader.h" +#include "nsPoint.h" #include "nsSize.h" #include "nsIURI.h" #include "nsAutoPtr.h" @@ -109,6 +110,47 @@ protected: {} public: + /** + * Defines a target configuration for this 's content + * document's viewport. If the content document's actual viewport + * doesn't match a desired ViewportConfig, then on paints its pixels + * are transformed to compensate for the difference. + * + * Used to support asynchronous re-paints of content pixels; see + * nsIFrameLoader.scrollViewport* and viewportScale. + */ + struct ViewportConfig { + ViewportConfig() + : mScrollOffset(0, 0) + , mXScale(1.0) + , mYScale(1.0) + {} + + // Default copy ctor and operator= are fine + + PRBool operator==(const ViewportConfig& aOther) const + { + return (mScrollOffset == aOther.mScrollOffset && + mXScale == aOther.mXScale && + mYScale == aOther.mYScale); + } + + // This is the scroll offset the user wishes or expects + // its enclosed content document to have. "Scroll offset" here + // means the document pixel at pixel (0,0) within the CSS + // viewport. If the content document's actual scroll offset + // doesn't match |mScrollOffset|, the difference is used to define + // a translation transform when painting the content document. + nsPoint mScrollOffset; + // The scale at which the user wishes to paint its + // enclosed content document. If content-document layers have a + // lower or higher resolution than the desired scale, then the + // ratio is used to define a scale transform when painting the + // content document. + float mXScale; + float mYScale; + }; + ~nsFrameLoader() { mNeedsAsyncDestroy = PR_TRUE; if (mMessageManager) { @@ -206,6 +248,8 @@ public: #endif nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; } + const ViewportConfig& GetViewportConfig() { return mViewportConfig; } + private: #ifdef MOZ_IPC @@ -238,6 +282,8 @@ private: bool ShowRemoteFrame(const nsIntSize& size); #endif + nsresult UpdateViewportConfig(const ViewportConfig& aNewConfig); + nsCOMPtr mDocShell; nsCOMPtr mURIToLoad; nsIContent *mOwnerContent; // WEAK @@ -268,6 +314,7 @@ private: TabParent* mRemoteBrowser; #endif + ViewportConfig mViewportConfig; }; #endif