Bug 487667 - Clone documents for printing, r=roc+jst+joe+dbaron

--HG--
extra : rebase_source : dbab242066ba97c0d7f34a2fb701a1c465f26ec4
This commit is contained in:
Olli Pettay 2009-12-10 20:02:13 -08:00
parent 01d27adee5
commit 423522c88b
73 changed files with 1422 additions and 495 deletions

View File

@ -670,6 +670,11 @@ public:
*/
static already_AddRefed<imgIContainer> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
/**
* Helper method to call imgIRequest::GetStaticRequest.
*/
static already_AddRefed<imgIRequest> GetStaticRequest(imgIRequest* aRequest);
/**
* Method that decides whether a content node is draggable
*

View File

@ -1159,6 +1159,25 @@ public:
PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
/**
* PR_TRUE when this document is a static clone of a normal document.
* For example print preview and printing use static documents.
*/
PRBool IsStaticDocument() { return mIsStaticDocument; }
/**
* Clones the document and subdocuments and stylesheet etc.
* @param aCloneContainer The container for the clone document.
*/
virtual already_AddRefed<nsIDocument>
CreateStaticClone(nsISupports* aCloneContainer);
/**
* If this document is a static clone, this returns the original
* document.
*/
nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
/**
* Called by nsParser to preload images. Can be removed and code moved
* to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
@ -1308,6 +1327,16 @@ protected:
// document has no window, DNS prefetch won't be performed no matter what.
PRPackedBool mAllowDNSPrefetch;
// True when this document is a static clone of a normal document
PRPackedBool mIsStaticDocument;
// True while this document is being cloned to a static document.
PRPackedBool mCreatingStaticClone;
// If mIsStaticDocument is true, mOriginalDocument points to the original
// document.
nsCOMPtr<nsIDocument> mOriginalDocument;
// The bidi options for this document. What this bitfield means is
// defined in nsBidiUtils.h
PRUint32 mBidiOptions;

View File

@ -37,6 +37,7 @@
#include "nsISupports.idl"
interface nsIFrame;
interface nsIObjectFrame;
interface nsIPluginInstance;
interface nsIDOMElement;
@ -45,7 +46,7 @@ interface nsIDOMClientRect;
/**
* This interface represents a content node that loads objects.
*/
[scriptable, uuid(8afe3b08-293c-48bd-a997-321745478611)]
[scriptable, uuid(7749d965-92f3-473e-b12d-de1e342acf1c)]
interface nsIObjectLoadingContent : nsISupports
{
const unsigned long TYPE_LOADING = 0;
@ -115,4 +116,12 @@ interface nsIObjectLoadingContent : nsISupports
void setAbsoluteScreenPosition(in nsIDOMElement element,
in nsIDOMClientRect position,
in nsIDOMClientRect clip);
/**
* If this object is in going to be printed, this method
* returns the nsIObjectFrame object which should be used when
* printing the plugin. The returned nsIFrame is in the original document,
* not in the static clone.
*/
[noscript] nsIFrame getPrintFrame();
};

View File

@ -2504,6 +2504,16 @@ nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
return imgContainer.forget();
}
//static
already_AddRefed<imgIRequest>
nsContentUtils::GetStaticRequest(imgIRequest* aRequest)
{
NS_ENSURE_TRUE(aRequest, nsnull);
nsCOMPtr<imgIRequest> retval;
aRequest->GetStaticRequest(getter_AddRefs(retval));
return retval.forget();
}
// static
PRBool
nsContentUtils::ContentIsDraggable(nsIContent* aContent)

View File

@ -3060,6 +3060,9 @@ nsDocument::doCreateShell(nsPresContext* aContext,
// Note: we don't hold a ref to the shell (it holds a ref to us)
NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell),
NS_ERROR_OUT_OF_MEMORY);
NS_WARN_IF_FALSE(mPresShells.Length() == 1, "More than one presshell!");
shell.swap(*aInstancePtrResult);
return NS_OK;
@ -7587,6 +7590,8 @@ nsDocument::QuerySelectorAll(const nsAString& aSelector,
nsresult
nsDocument::CloneDocHelper(nsDocument* clone) const
{
clone->mIsStaticDocument = mCreatingStaticClone;
// Init document
nsresult rv = clone->Init();
NS_ENSURE_SUCCESS(rv, rv);
@ -7597,6 +7602,21 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
clone->SetPrincipal(NodePrincipal());
clone->mDocumentBaseURI = mDocumentBaseURI;
if (mCreatingStaticClone) {
nsCOMPtr<nsIChannel> channel = GetChannel();
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
if (channel && loadGroup) {
clone->Reset(channel, loadGroup);
} else {
nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
if (uri) {
clone->ResetToURI(uri, loadGroup, NodePrincipal());
}
}
nsCOMPtr<nsISupports> container = GetContainer();
clone->SetContainer(container);
}
// Set scripting object
PRBool hasHadScriptObject = PR_TRUE;
nsIScriptGlobalObject* scriptObject =
@ -7821,3 +7841,67 @@ nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
EnumerateFreezablesData data = { aEnumerator, aData };
mFreezableElements->EnumerateEntries(EnumerateFreezables, &data);
}
already_AddRefed<nsIDocument>
nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
{
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
NS_ENSURE_TRUE(domDoc, nsnull);
mCreatingStaticClone = PR_TRUE;
// Make document use different container during cloning.
nsCOMPtr<nsISupports> originalContainer = GetContainer();
SetContainer(aCloneContainer);
nsCOMPtr<nsIDOMNode> clonedNode;
nsresult rv = domDoc->CloneNode(PR_TRUE, getter_AddRefs(clonedNode));
SetContainer(originalContainer);
nsCOMPtr<nsIDocument> clonedDoc;
if (NS_SUCCEEDED(rv)) {
clonedDoc = do_QueryInterface(clonedNode);
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
if (clonedDOMDoc) {
clonedDoc->mOriginalDocument = this;
PRInt32 sheetsCount = GetNumberOfStyleSheets();
for (PRInt32 i = 0; i < sheetsCount; ++i) {
nsCOMPtr<nsICSSStyleSheet> sheet =
do_QueryInterface(GetStyleSheetAt(i));
if (sheet) {
PRBool applicable = PR_TRUE;
sheet->GetApplicable(applicable);
if (applicable) {
nsCOMPtr<nsICSSStyleSheet> clonedSheet;
sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
getter_AddRefs(clonedSheet));
NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
if (clonedSheet) {
clonedDoc->AddStyleSheet(clonedSheet);
}
}
}
}
sheetsCount = GetNumberOfCatalogStyleSheets();
for (PRInt32 i = 0; i < sheetsCount; ++i) {
nsCOMPtr<nsICSSStyleSheet> sheet =
do_QueryInterface(GetCatalogStyleSheetAt(i));
if (sheet) {
PRBool applicable = PR_TRUE;
sheet->GetApplicable(applicable);
if (applicable) {
nsCOMPtr<nsICSSStyleSheet> clonedSheet;
sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
getter_AddRefs(clonedSheet));
NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
if (clonedSheet) {
clonedDoc->AddCatalogStyleSheet(clonedSheet);
}
}
}
}
}
}
mCreatingStaticClone = PR_FALSE;
return clonedDoc.forget();
}

View File

@ -87,6 +87,8 @@
#include "nsINameSpaceManager.h"
#include "nsThreadUtils.h"
#include "nsICSSStyleSheet.h"
#include "nsIContentViewer.h"
class nsAsyncDocShellDestroyer : public nsRunnable
{
@ -138,9 +140,11 @@ nsFrameLoader*
nsFrameLoader::Create(nsIContent* aOwner)
{
NS_ENSURE_TRUE(aOwner, nsnull);
nsIDocument* doc = aOwner->GetCurrentDoc();
nsIDocument* doc = aOwner->GetOwnerDoc();
NS_ENSURE_TRUE(doc && !doc->GetDisplayDocument() &&
!doc->IsLoadedAsData(), nsnull);
((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
doc->IsStaticDocument()),
nsnull);
return new nsFrameLoader(aOwner);
}
@ -160,7 +164,7 @@ nsFrameLoader::LoadFrame()
}
nsIDocument* doc = mOwnerContent->GetOwnerDoc();
if (!doc) {
if (!doc || doc->IsStaticDocument()) {
return NS_OK;
}
@ -910,8 +914,8 @@ nsFrameLoader::EnsureDocShell()
// Get our parent docshell off the document of mOwnerContent
// XXXbz this is such a total hack.... We really need to have a
// better setup for doing this.
nsIDocument* doc = mOwnerContent->GetDocument();
if (!doc) {
nsIDocument* doc = mOwnerContent->GetOwnerDoc();
if (!doc || !(doc->IsStaticDocument() || mOwnerContent->IsInDoc())) {
return NS_ERROR_UNEXPECTED;
}
@ -920,8 +924,9 @@ nsFrameLoader::EnsureDocShell()
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIWebNavigation> parentAsWebNav =
do_GetInterface(doc->GetScriptGlobalObject());
nsCOMPtr<nsISupports> container =
doc->GetContainer();
nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
// Create the docshell...
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
@ -1123,3 +1128,28 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
return NS_OK;
}
nsresult
nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
{
nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
dest->EnsureDocShell();
NS_ENSURE_STATE(dest->mDocShell);
nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(dest->mDocShell);
nsCOMPtr<nsIContentViewer> viewer;
dest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
NS_ENSURE_STATE(viewer);
nsCOMPtr<nsIDocShell> origDocShell;
GetDocShell(getter_AddRefs(origDocShell));
nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(origDocShell);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
viewer->SetDOMDocument(clonedDOMDoc);
return NS_OK;
}

View File

@ -81,6 +81,8 @@ public:
void Finalize();
nsIDocShell* GetExistingDocShell() { return mDocShell; }
nsresult CreateStaticClone(nsIFrameLoader* aDest);
/**
* Called from the layout frame associated with this frame loader;
* this notifies us to hook up with the widget and view.
@ -96,6 +98,8 @@ public:
*/
void Hide();
nsresult CloneForStatic(nsIFrameLoader* aOriginal);
// The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation. A
// frame loader owner needs to call this, and pass in the two references to
// nsRefPtrs for frame loaders that need to be swapped.

View File

@ -201,7 +201,6 @@ GK_ATOM(click, "click")
GK_ATOM(clickcount, "clickcount")
GK_ATOM(movetoclick, "movetoclick")
GK_ATOM(clip, "clip")
GK_ATOM(clonedTextForPrint, "clonedTextForPrint")
GK_ATOM(close, "close")
GK_ATOM(closed, "closed")
GK_ATOM(closemenu, "closemenu")

View File

@ -987,3 +987,19 @@ nsImageLoadingContent::SetBlockingOnload(PRBool aBlocking)
mBlockingOnload = aBlocking;
}
}
void
nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const
{
aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest);
aDest->mForcedImageState = mForcedImageState;
aDest->mImageBlockingStatus = mImageBlockingStatus;
aDest->mLoadingEnabled = mLoadingEnabled;
aDest->mStartingLoad = mStartingLoad;
aDest->mIsImageStateForced = mIsImageStateForced;
aDest->mLoading = mLoading;
aDest->mBroken = mBroken;
aDest->mUserDisabled = mUserDisabled;
aDest->mSuppressed = mSuppressed;
}

View File

@ -247,9 +247,10 @@ private:
nsresult FireEvent(const nsAString& aEventType);
class Event;
friend class Event;
protected:
void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
/* MEMBERS */
protected:
nsCOMPtr<imgIRequest> mCurrentRequest;
nsCOMPtr<imgIRequest> mPendingRequest;
nsCOMPtr<nsIURI> mCurrentURI;

View File

@ -812,6 +812,14 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
LOG(("OBJLC [%p]: Got frame %p (mInstantiating=%i)\n", this, aFrame,
mInstantiating));
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ASSERTION(thisContent, "must be a content");
nsIDocument* doc = thisContent->GetOwnerDoc();
if (!doc || doc->IsStaticDocument()) {
return NS_OK;
}
// "revoke" any existing instantiate event as it likely has out of
// date data (frame pointer etc).
mPendingInstantiateEvent = nsnull;
@ -1098,7 +1106,9 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Security checks
if (doc->IsLoadedAsData()) {
Fallback(PR_FALSE);
if (!doc->IsStaticDocument()) {
Fallback(PR_FALSE);
}
return NS_OK;
}
@ -1876,6 +1886,40 @@ nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
return ePluginUnsupported;
}
void
nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
{
nsImageLoadingContent::CreateStaticImageClone(aDest);
aDest->mType = mType;
nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
if (thisObj->mPrintFrame.IsAlive()) {
aDest->mPrintFrame = thisObj->mPrintFrame;
} else {
nsIObjectFrame* frame =
const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame(eDontFlush);
nsIFrame* f = do_QueryFrame(frame);
aDest->mPrintFrame = f;
}
if (mFrameLoader) {
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>((aDest)));
nsFrameLoader* fl = nsFrameLoader::Create(content);
if (fl) {
aDest->mFrameLoader = fl;
mFrameLoader->CreateStaticClone(fl);
}
}
}
NS_IMETHODIMP
nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
{
*aFrame = mPrintFrame.GetFrame();
return NS_OK;
}
NS_IMETHODIMP
nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
nsIDOMClientRect* position,

View File

@ -53,6 +53,7 @@
#include "nsIObjectLoadingContent.h"
#include "nsIRunnable.h"
#include "nsIChannelClassifier.h"
#include "nsIFrame.h"
class nsAsyncInstantiateEvent;
class AutoNotifier;
@ -223,6 +224,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
void Traverse(nsCycleCollectionTraversalCallback &cb);
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
private:
/**
* Check whether the given request represents a successful load.
@ -422,6 +424,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// A specific state that caused us to fallback
PluginSupportState mPluginState;
nsWeakFrame mPrintFrame;
friend class nsAsyncInstantiateEvent;
};

View File

@ -222,7 +222,9 @@ nsStyledElement::ParseStyleAttribute(nsIContent* aContent,
nsresult result = NS_OK;
nsIDocument* doc = aContent->GetOwnerDoc();
if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) {
if (doc && (aForceInDataDoc ||
!doc->IsLoadedAsData() ||
doc->IsStaticDocument())) {
PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
if (!aContent->IsInNativeAnonymousSubtree()) { // native anonymous content

View File

@ -267,8 +267,9 @@ public:
* Returns PR_TRUE if the media has played or completed a seek.
* Used by video frame to determine whether to paint the poster.
*/
PRBool GetPlayedOrSeeked() { return mHasPlayedOrSeeked; }
PRBool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; }
nsresult CopyInnerTo(nsGenericElement* aDest) const;
protected:
class MediaLoadListener;
class LoadNextSourceEvent;
@ -519,4 +520,6 @@ protected:
// alive while no-one is referencing it but the element may still fire
// events of its own accord.
PRPackedBool mHasSelfReference;
nsRefPtr<gfxASurface> mPrintSurface;
};

View File

@ -127,6 +127,8 @@ INCLUDES += \
-I$(srcdir)/../../../xbl/src \
-I$(srcdir)/../../../../layout/style \
-I$(srcdir)/../../../../layout/tables \
-I$(srcdir)/../../../../layout/xul/base/src \
-I$(srcdir)/../../../../layout/generic \
-I$(srcdir)/../../../../dom/base \
-I$(srcdir) \
$(NULL)

View File

@ -2869,6 +2869,25 @@ nsGenericHTMLFrameElement::DestroyContent()
nsGenericHTMLElement::DestroyContent();
}
nsresult
nsGenericHTMLFrameElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
nsIDocument* doc = aDest->GetOwnerDoc();
if (doc->IsStaticDocument() && mFrameLoader) {
nsGenericHTMLFrameElement* dest =
static_cast<nsGenericHTMLFrameElement*>(aDest);
nsFrameLoader* fl = nsFrameLoader::Create(dest);
NS_ENSURE_STATE(fl);
dest->mFrameLoader = fl;
static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
}
return rv;
}
//----------------------------------------------------------------------
nsresult

View File

@ -917,6 +917,8 @@ public:
PRBool aNotify);
virtual void DestroyContent();
nsresult CopyInnerTo(nsGenericElement* aDest) const;
// nsIDOMNSHTMLElement
NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);

View File

@ -58,7 +58,7 @@
#include "nsIRenderingContext.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "nsLayoutUtils.h"
#define DEFAULT_CANVAS_WIDTH 300
@ -118,7 +118,7 @@ public:
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
protected:
nsIntSize GetWidthHeight();
@ -218,6 +218,24 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
return rv;
}
nsresult
nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
nsHTMLCanvasElement* dest = static_cast<nsHTMLCanvasElement*>(aDest);
nsCOMPtr<nsISupports> cxt;
dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
nsCOMPtr<nsIDOMCanvasRenderingContext2D> context2d = do_QueryInterface(cxt);
if (context2d) {
context2d->DrawImage(const_cast<nsHTMLCanvasElement*>(this),
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
}
}
return rv;
}
nsChangeHint
nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
PRInt32 aModType) const

View File

@ -148,6 +148,8 @@ public:
virtual PRInt32 IntrinsicState() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
void MaybeLoadImage();
protected:
nsPoint GetXY();
@ -658,4 +660,11 @@ nsHTMLImageElement::GetNaturalWidth(PRInt32* aNaturalWidth)
return NS_OK;
}
nsresult
nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
{
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest));
}
return nsGenericHTMLElement::CopyInnerTo(aDest);
}

View File

@ -557,6 +557,11 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
it->DoSetChecked(checked, PR_FALSE);
}
break;
case NS_FORM_INPUT_IMAGE:
if (it->GetOwnerDoc()->IsStaticDocument()) {
CreateStaticImageClone(it);
}
break;
default:
break;
}

View File

@ -78,6 +78,8 @@
#include "nsContentErrors.h"
#include "nsCrossSiteListenerProxy.h"
#include "nsCycleCollectionParticipant.h"
#include "nsLayoutUtils.h"
#include "nsVideoFrame.h"
#ifdef MOZ_OGG
#include "nsOggDecoder.h"
@ -1084,7 +1086,8 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
PRBool aCompileEventHandlers)
{
mIsBindingToTree = PR_TRUE;
mAutoplayEnabled = IsAutoplayEnabled();
mAutoplayEnabled =
IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument());
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
aParent,
aBindingParent,
@ -1711,8 +1714,22 @@ void nsHTMLMediaElement::Paint(gfxContext* aContext,
gfxPattern::GraphicsFilter aFilter,
const gfxRect& aRect)
{
if (mDecoder)
if (mPrintSurface) {
nsRefPtr<gfxPattern> pat = new gfxPattern(mPrintSurface);
if (!pat)
return;
// Make the source image fill the rectangle completely
pat->SetMatrix(gfxMatrix().Scale(mMediaSize.width/aRect.Width(),
mMediaSize.height/aRect.Height()));
pat->SetFilter(aFilter);
aContext->NewPath();
aContext->PixelSnappedRectangleAndSetPattern(aRect, pat);
aContext->Fill();
} else if (mDecoder) {
mDecoder->Paint(aContext, aFilter, aRect);
}
}
nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName)
@ -1995,3 +2012,36 @@ already_AddRefed<nsILoadGroup> nsHTMLMediaElement::GetDocumentLoadGroup()
nsIDocument* doc = GetOwnerDoc();
return doc ? doc->GetDocumentLoadGroup() : nsnull;
}
nsresult
nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
nsHTMLMediaElement* dest = static_cast<nsHTMLMediaElement*>(aDest);
if (mPrintSurface) {
dest->mPrintSurface = mPrintSurface;
dest->mMediaSize = mMediaSize;
} else {
nsIFrame* frame =
GetPrimaryFrameFor(const_cast<nsHTMLMediaElement*>(this),
GetOwnerDoc());
nsCOMPtr<nsIDOMElement> elem;
if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
elem = do_QueryInterface(static_cast<nsVideoFrame*>(frame)->
GetPosterImage());
} else {
elem = do_QueryInterface(const_cast<nsHTMLMediaElement*>(this));
}
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(elem,
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
dest->mPrintSurface = res.mSurface;
dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height);
}
}
return rv;
}

View File

@ -123,6 +123,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
void StartObjectLoad() { StartObjectLoad(PR_TRUE); }
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLObjectElement,
@ -478,3 +480,16 @@ nsHTMLObjectElement::DestroyContent()
RemovedFromDocument();
nsGenericHTMLFormElement::DestroyContent();
}
nsresult
nsHTMLObjectElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
CreateStaticClone(static_cast<nsHTMLObjectElement*>(aDest));
}
return rv;
}

View File

@ -120,6 +120,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
protected:
/**
* Get the select content element that contains this option, this
@ -528,3 +530,18 @@ nsHTMLOptionElement::Initialize(nsISupports* aOwner,
return result;
}
nsresult
nsHTMLOptionElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
PRBool selected = PR_FALSE;
const_cast<nsHTMLOptionElement*>(this)->GetSelected(&selected);
static_cast<nsHTMLOptionElement*>(aDest)->SetSelected(selected);
}
return NS_OK;
}

View File

@ -130,6 +130,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
void StartObjectLoad() { StartObjectLoad(PR_TRUE); }
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSharedObjectElement,
@ -460,3 +462,16 @@ nsHTMLSharedObjectElement::DestroyContent()
RemovedFromDocument();
nsGenericHTMLElement::DestroyContent();
}
nsresult
nsHTMLSharedObjectElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
CreateStaticClone(static_cast<nsHTMLSharedObjectElement*>(aDest));
}
return rv;
}

View File

@ -150,6 +150,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
/**
* Called when an attribute is about to be changed
*/
@ -975,3 +977,18 @@ nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
}
nsresult
nsHTMLTextAreaElement::CopyInnerTo(nsGenericElement* aDest) const
{
nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
nsAutoString value;
const_cast<nsHTMLTextAreaElement*>(this)->GetValue(value);
static_cast<nsHTMLTextAreaElement*>(aDest)->SetValue(value);
}
return NS_OK;
}

View File

@ -269,3 +269,12 @@ nsSVGImageElement::GetStringInfo()
return StringAttributesInfo(mStringAttributes, sStringInfo,
NS_ARRAY_LENGTH(sStringInfo));
}
nsresult
nsSVGImageElement::CopyInnerTo(nsGenericElement* aDest) const
{
if (aDest->GetOwnerDoc()->IsStaticDocument()) {
CreateStaticImageClone(static_cast<nsSVGImageElement*>(aDest));
}
return nsSVGImageElementBase::CopyInnerTo(aDest);
}

View File

@ -90,6 +90,8 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
nsresult CopyInnerTo(nsGenericElement* aDest) const;
void MaybeLoadSVGImage();
protected:
nsresult LoadSVGImage(PRBool aForce, PRBool aNotify);

View File

@ -129,6 +129,20 @@ nsSVGDocument::GetRootElement(nsIDOMSVGSVGElement** aRootElement)
return root ? CallQueryInterface(root, aRootElement) : NS_OK;
}
nsresult
nsSVGDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
{
NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
"Can't import this document into another document!");
nsRefPtr<nsSVGDocument> clone = new nsSVGDocument();
NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = CloneDocHelper(clone.get());
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(clone.get(), aResult);
}
////////////////////////////////////////////////////////////////////////
// Exported creation functions

View File

@ -54,7 +54,7 @@ class nsSVGDocument : public nsXMLDocument,
NS_FORWARD_NSIDOMNODE(nsXMLDocument::)
NS_FORWARD_NSIDOMDOCUMENTEVENT(nsXMLDocument::)
NS_DECL_ISUPPORTS_INHERITED
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
};
#endif

View File

@ -103,4 +103,6 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += -I$(srcdir)/../shistory/src
LOCAL_INCLUDES += -I$(srcdir)/../shistory/src \
-I$(srcdir)/../../layout/base \
$(NULL)

View File

@ -202,6 +202,11 @@
// for embedding
#include "nsIWebBrowserChromeFocus.h"
#if NS_PRINT_PREVIEW
#include "nsIDocumentViewerPrint.h"
#include "nsIWebBrowserPrint.h"
#endif
#include "nsPluginError.h"
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
@ -11072,6 +11077,32 @@ nsDocShell::SetRendering(PRBool aRender)
return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
}
NS_IMETHODIMP
nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
{
*aPrintPreview = nsnull;
#if NS_PRINT_PREVIEW
nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
if (!print || !print->IsInitializedForPrintPreview()) {
Stop(nsIWebNavigation::STOP_ALL);
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance("@mozilla.org/nullprincipal;1");
NS_ENSURE_STATE(principal);
nsresult rv = CreateAboutBlankContentViewer(principal, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
print = do_QueryInterface(mContentViewer);
NS_ENSURE_STATE(print);
print->InitializeForPrintPreview();
}
nsCOMPtr<nsIWebBrowserPrint> result = do_QueryInterface(print);
result.forget(aPrintPreview);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
#ifdef DEBUG
unsigned long nsDocShell::gNumberOfDocShells = 0;
#endif

View File

@ -68,8 +68,9 @@ interface nsILayoutHistoryState;
interface nsISecureBrowserUI;
interface nsIDOMStorage;
interface nsIPrincipal;
interface nsIWebBrowserPrint;
[scriptable, uuid(8ADFB831-1053-4A19-884D-BCDAD7277B4B)]
[scriptable, uuid(1067ee1a-08e8-455d-9b12-19eeeee56b8e)]
interface nsIDocShell : nsISupports
{
/**
@ -488,4 +489,11 @@ interface nsIDocShell : nsISupports
* and should be treated accordingly.
**/
attribute boolean isOffScreenBrowser;
/**
* If the current content viewer isn't initialized for print preview,
* it is replaced with one which is and to which an about:blank document
* is loaded.
*/
readonly attribute nsIWebBrowserPrint printPreview;
};

View File

@ -144,7 +144,7 @@ interface nsIWebBrowserPrint : nsISupports
*
* @param aThePrintSettings - Printer Settings for the print preview, if aThePrintSettings is null
* then the global PS will be used.
* @param aChildDOMWin - DOM Window of the child document to be PP (FrameSet frames)
* @param aChildDOMWin - DOM Window to be print previewed.
* @param aWPListener - is updated during the printpreview
* @return void
*/

View File

@ -11614,8 +11614,7 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
mRebuildAllExtraHint = nsChangeHint(0);
if (!mPresShell || !mPresShell->GetRootFrame() ||
!mPresShell->GetPresContext()->IsDynamic())
if (!mPresShell || !mPresShell->GetRootFrame())
return;
nsAutoScriptBlocker scriptBlocker;

View File

@ -498,7 +498,7 @@ protected:
PRPackedBool mIsPageMode;
PRPackedBool mCallerIsClosingWindow;
PRPackedBool mInitializedForPrintPreview;
};
//------------------------------------------------------------------
@ -540,11 +540,10 @@ void DocumentViewerImpl::PrepareToStartLoad()
if (mPrintEngine) {
mPrintEngine->Destroy();
mPrintEngine = nsnull;
}
#ifdef NS_PRINT_PREVIEW
SetIsPrintPreview(PR_FALSE);
SetIsPrintPreview(PR_FALSE);
#endif
}
#ifdef NS_DEBUG
mDebugFile = nsnull;
@ -560,7 +559,8 @@ DocumentViewerImpl::DocumentViewerImpl()
#ifdef NS_PRINT_PREVIEW
mPrintPreviewZoom(1.0),
#endif
mHintCharsetSource(kCharsetUninitialized)
mHintCharsetSource(kCharsetUninitialized),
mInitializedForPrintPreview(PR_FALSE)
{
PrepareToStartLoad();
}
@ -700,6 +700,9 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget,
nsresult
DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh)
{
if (GetIsPrintPreview())
return NS_OK;
NS_ASSERTION(!mPresShell,
"Someone should have destroyed the presshell!");
@ -1700,14 +1703,16 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
// Clear the list of old child docshells. CChild docshells for the new
// document will be constructed as frames are created.
nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
if (node) {
PRInt32 count;
node->GetChildCount(&count);
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDocShellTreeItem> child;
node->GetChildAt(0, getter_AddRefs(child));
node->RemoveChild(child);
if (!newDoc->IsStaticDocument()) {
nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
if (node) {
PRInt32 count;
node->GetChildCount(&count);
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDocShellTreeItem> child;
node->GetChildAt(0, getter_AddRefs(child));
node->RemoveChild(child);
}
}
}
}
@ -1767,37 +1772,19 @@ DocumentViewerImpl::GetDocument(nsIDocument** aResult)
nsIPresShell*
DocumentViewerImpl::GetPresShell()
{
if (!GetIsPrintPreview()) {
return mPresShell;
}
NS_ENSURE_TRUE(mDocument, nsnull);
nsCOMPtr<nsIPresShell> shell;
nsCOMPtr<nsIPresShell> currentShell;
nsPresShellIterator iter(mDocument);
while ((shell = iter.GetNextShell())) {
currentShell.swap(shell);
}
return currentShell.get();
return mPresShell;
}
nsPresContext*
DocumentViewerImpl::GetPresContext()
{
if (!GetIsPrintPreview()) {
return mPresContext;
}
nsIPresShell* shell = GetPresShell();
return shell ? shell->GetPresContext() : nsnull;
return mPresContext;
}
nsIViewManager*
DocumentViewerImpl::GetViewManager()
{
if (!GetIsPrintPreview()) {
return mViewManager;
}
nsIPresShell* shell = GetPresShell();
return shell ? shell->GetViewManager() : nsnull;
return mViewManager;
}
NS_IMETHODIMP
@ -2011,8 +1998,10 @@ DocumentViewerImpl::Show(void)
// window is shown because some JS on the page caused it to be
// shown...
nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
mPresShell->UnsuppressPainting();
if (mPresShell) {
nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
mPresShell->UnsuppressPainting();
}
}
return NS_OK;
@ -2285,8 +2274,10 @@ DocumentViewerImpl::ClearHistoryEntry()
nsresult
DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
{
nsresult rv;
if (GetIsPrintPreview())
return NS_OK;
nsresult rv;
mViewManager = do_CreateInstance(kViewManagerCID, &rv);
if (NS_FAILED(rv))
return rv;
@ -3774,6 +3765,10 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener)
{
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
NS_WARN_IF_FALSE(IsInitializedForPrintPreview(),
"Using docshell.printPreview is the preferred way for print previewing!");
NS_ENSURE_ARG_POINTER(aChildDOMWin);
nsresult rv = NS_OK;
if (GetIsPrinting()) {
@ -3791,25 +3786,23 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings,
}
#endif
if (!mContainer) {
PR_PL(("Container was destroyed yet we are still trying to use it!"));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
NS_ASSERTION(docShell, "This has to be a docshell");
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
if (!presShell || !mDocument || !mDeviceContext || !mParentWidget) {
PR_PL(("Can't Print Preview without pres shell, document etc"));
if (!docShell ||! mDeviceContext || !mParentWidget) {
PR_PL(("Can't Print Preview without device context, docshell etc"));
return NS_ERROR_FAILURE;
}
if (!mPrintEngine) {
nsCOMPtr<nsIDOMDocument> domDoc;
aChildDOMWin->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
NS_ENSURE_STATE(doc);
mPrintEngine = new nsPrintEngine();
NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
rv = mPrintEngine->Initialize(this, docShell, mDocument,
rv = mPrintEngine->Initialize(this, docShell, doc,
float(mDeviceContext->AppUnitsPerInch()) /
float(mDeviceContext->AppUnitsPerDevPixel()) /
mPageZoom,
@ -4224,6 +4217,12 @@ DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview)
SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, PR_TRUE);
}
#endif
if (!aIsPrintPreview) {
mWindow = nsnull;
mViewManager = nsnull;
mPresContext = nsnull;
mPresShell = nsnull;
}
}
//----------------------------------------------------------------------------------
@ -4256,14 +4255,13 @@ DocumentViewerImpl::ReturnToGalleyPresentation()
mPrintEngine->Destroy();
mPrintEngine = nsnull;
mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
if (mViewManager) {
mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
}
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
ResetFocusState(docShell);
if (mPresContext)
mPresContext->RestoreImageAnimationMode();
SetTextZoom(mTextZoom);
SetFullZoom(mPageZoom);
Show();
@ -4335,8 +4333,6 @@ DocumentViewerImpl::OnDonePrinting()
}
mClosingWhilePrinting = PR_FALSE;
}
if (mPresContext)
mPresContext->RestoreImageAnimationMode();
}
#endif // NS_PRINTING && NS_PRINT_PREVIEW
}
@ -4402,3 +4398,31 @@ DocumentViewerImpl::DestroyPresShell()
mPresShell->Destroy();
mPresShell = nsnull;
}
PRBool
DocumentViewerImpl::IsInitializedForPrintPreview()
{
return mInitializedForPrintPreview;
}
void
DocumentViewerImpl::InitializeForPrintPreview()
{
mInitializedForPrintPreview = PR_TRUE;
}
void
DocumentViewerImpl::SetPrintPreviewPresentation(nsIWidget* aWidget,
nsIViewManager* aViewManager,
nsPresContext* aPresContext,
nsIPresShell* aPresShell)
{
if (mPresShell) {
DestroyPresShell();
}
mWindow = aWidget;
mViewManager = aViewManager;
mPresContext = aPresContext;
mPresShell = aPresShell;
}

View File

@ -41,10 +41,15 @@
class nsIDocument;
class nsStyleSet;
class nsIPresShell;
class nsPresContext;
class nsIWidget;
class nsIViewManager;
// {D0B7F354-D575-43fd-903D-5AA35A193EDA}
// {c6f255cf-cadd-4382-b57f-cd2a9874169b}
#define NS_IDOCUMENT_VIEWER_PRINT_IID \
{ 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } }
{ 0xc6f255cf, 0xcadd, 0x4382, \
{ 0xb5, 0x7f, 0xcd, 0x2a, 0x98, 0x74, 0x16, 0x9b } }
/**
* A DocumentViewerPrint is an INTERNAL Interface used for interaction
@ -72,6 +77,23 @@ public:
virtual void OnDonePrinting() = 0;
/**
* Returns PR_TRUE is InitializeForPrintPreview() has been called.
*/
virtual PRBool IsInitializedForPrintPreview() = 0;
/**
* Marks this viewer to be used for print preview.
*/
virtual void InitializeForPrintPreview() = 0;
/**
* Replaces the current presentation with print preview presentation.
*/
virtual void SetPrintPreviewPresentation(nsIWidget* aWidget,
nsIViewManager* aViewManager,
nsPresContext* aPresContext,
nsIPresShell* aPresShell) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
@ -86,6 +108,12 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet); \
virtual void IncrementDestroyRefCount(); \
virtual void ReturnToGalleyPresentation(); \
virtual void OnDonePrinting();
virtual void OnDonePrinting(); \
virtual PRBool IsInitializedForPrintPreview(); \
virtual void InitializeForPrintPreview(); \
virtual void SetPrintPreviewPresentation(nsIWidget* aWidget, \
nsIViewManager* aViewManager, \
nsPresContext* aPresContext, \
nsIPresShell* aPresShell);
#endif /* nsIDocumentViewerPrint_h___ */

View File

@ -78,7 +78,6 @@
#include "gfxTypes.h"
#include "gfxUserFontSet.h"
#include "nsTArray.h"
#include "nsTextFragment.h"
#include "nsICanvasElement.h"
#include "nsICanvasRenderingContextInternal.h"
#include "gfxPlatform.h"
@ -3275,48 +3274,6 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame)
parentType == nsGkAtoms::pageContentFrame;
}
static void DeleteTextFragment(void* aObject, nsIAtom* aPropertyName,
void* aPropertyValue, void* aData)
{
delete static_cast<nsTextFragment*>(aPropertyValue);
}
/* static */ nsTextFragment*
nsLayoutUtils::GetTextFragmentForPrinting(const nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
NS_PRECONDITION(!presContext->IsDynamic(),
"Shouldn't call this with dynamic PresContext");
#ifdef MOZ_SVG
NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame ||
aFrame->GetType() == nsGkAtoms::svgGlyphFrame,
"Wrong frame type!");
#else
NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame,
"Wrong frame type!");
#endif // MOZ_SVG
nsIContent* content = aFrame->GetContent();
nsTextFragment* frag =
static_cast<nsTextFragment*>(presContext->PropertyTable()->
GetProperty(content, nsGkAtoms::clonedTextForPrint));
if (!frag) {
frag = new nsTextFragment();
NS_ENSURE_TRUE(frag, nsnull);
*frag = *content->GetText();
nsresult rv = presContext->PropertyTable()->
SetProperty(content, nsGkAtoms::clonedTextForPrint, frag,
DeleteTextFragment, nsnull);
if (NS_FAILED(rv)) {
delete frag;
return nsnull;
}
}
return frag;
}
nsLayoutUtils::SurfaceFromElementResult
nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
PRUint32 aSurfaceFlags)

View File

@ -67,7 +67,6 @@ class nsClientRectList;
#include "nsCSSPseudoElements.h"
class nsBlockFrame;
class nsTextFragment;
/**
* nsLayoutUtils is a namespace class used for various helper
@ -1063,12 +1062,6 @@ public:
*/
static PRBool sDisableGetUsedXAssertions;
/**
* Returns the text fragment, which aFrame should use for printing.
* @param aFrame The nsIFrame object, which uses text fragment data.
*/
static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame);
/**
* Return true if aFrame is in an {ib} split and is NOT one of the
* continuations of the first inline in it.

View File

@ -1229,7 +1229,7 @@ nsPresContext::GetDefaultFont(PRUint8 aFontID) const
void
nsPresContext::SetFullZoom(float aZoom)
{
if (!mShell || mFullZoom == aZoom || !IsDynamic()) {
if (!mShell || mFullZoom == aZoom) {
return;
}
// Re-fetch the view manager's window dimensions in case there's a deferred

View File

@ -103,6 +103,7 @@ class nsUserFontSet;
struct nsFontFaceRuleContainer;
class nsObjectFrame;
class nsTransitionManager;
class imgIContainer;
#ifdef MOZ_REFLOW_PERF
class nsIRenderingContext;
@ -278,7 +279,6 @@ public:
* Access the image animation mode for this context
*/
PRUint16 ImageAnimationMode() const { return mImageAnimationMode; }
void RestoreImageAnimationMode() { SetImageAnimationMode(mImageAnimationModePref); }
virtual NS_HIDDEN_(void) SetImageAnimationModeExternal(PRUint16 aMode);
NS_HIDDEN_(void) SetImageAnimationModeInternal(PRUint16 aMode);
#ifdef _IMPL_NS_LAYOUT

View File

@ -1223,9 +1223,6 @@ protected:
static PRBool sDisableNonTestMouseEvents;
nsCOMPtr<nsIDocumentObserver> mDocumentObserverForNonDynamicContext;
// false if a check should be done for key/ime events that should be
// retargeted to the currently focused presshell
static PRBool sDontRetargetEvents;
@ -1340,122 +1337,6 @@ public:
nsRefPtr<PresShell> mPresShell;
};
class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
{
public:
nsDocumentObserverForNonDynamicPresContext(PresShell* aBaseObserver)
: mBaseObserver(aBaseObserver)
{
NS_ASSERTION(aBaseObserver, "Null document observer!");
}
NS_DECL_ISUPPORTS
virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
{
mBaseObserver->BeginUpdate(aDocument, aUpdateType);
}
virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
{
mBaseObserver->EndUpdate(aDocument, aUpdateType);
}
virtual void BeginLoad(nsIDocument* aDocument)
{
mBaseObserver->BeginLoad(aDocument);
}
virtual void EndLoad(nsIDocument* aDocument)
{
mBaseObserver->EndLoad(aDocument);
}
virtual void ContentStatesChanged(nsIDocument* aDocument,
nsIContent* aContent1,
nsIContent* aContent2,
PRInt32 aStateMask)
{
if ((!aContent1 || AllowMutation(aContent1)) &&
(!aContent2 || AllowMutation(aContent2))) {
mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
aStateMask);
}
}
// nsIMutationObserver
virtual void CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
if (AllowMutation(aContent)) {
mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
}
}
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (AllowMutation(aContent)) {
mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
aAttribute, aModType);
}
}
virtual void ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
if (AllowMutation(aContainer)) {
mBaseObserver->ContentAppended(aDocument, aContainer,
aNewIndexInContainer);
}
}
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (AllowMutation(aContainer)) {
mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
aIndexInContainer);
}
}
virtual void ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (AllowMutation(aContainer)) {
mBaseObserver->ContentRemoved(aDocument, aContainer, aChild,
aIndexInContainer);
}
}
PRBool AllowMutation(nsIContent* aContent) {
if(aContent && aContent->IsInDoc()) {
if (mBaseObserver->ObservesNativeAnonMutationsForPrint() &&
aContent->IsInNativeAnonymousSubtree()) {
return PR_TRUE;
}
// Changes to scrollbar are always ok.
nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
while (aContent && aContent->IsInNativeAnonymousSubtree()) {
nsIContent* parent = aContent->GetParent();
if (parent == root && aContent->IsXUL()) {
nsIAtom* tag = aContent->Tag();
return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
}
aContent = parent;
}
}
return PR_FALSE;
}
protected:
nsRefPtr<PresShell> mBaseObserver;
};
NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
nsIDocumentObserver,
nsIMutationObserver)
PRBool PresShell::sDisableNonTestMouseEvents = PR_FALSE;
PRBool PresShell::sDontRetargetEvents = PR_FALSE;
@ -2532,14 +2413,7 @@ NS_IMETHODIMP
PresShell::BeginObservingDocument()
{
if (mDocument && !mIsDestroying) {
if (mPresContext->IsDynamic()) {
mDocument->AddObserver(this);
} else {
mDocumentObserverForNonDynamicContext =
new nsDocumentObserverForNonDynamicPresContext(this);
NS_ENSURE_TRUE(mDocumentObserverForNonDynamicContext, NS_ERROR_OUT_OF_MEMORY);
mDocument->AddObserver(mDocumentObserverForNonDynamicContext);
}
mDocument->AddObserver(this);
if (mIsDocumentGone) {
NS_WARNING("Adding a presshell that was disconnected from the document "
"as a document observer? Sounds wrong...");
@ -2557,10 +2431,7 @@ PresShell::EndObservingDocument()
// is gone, perhaps? Except for printing it's NOT gone, sometimes.
mIsDocumentGone = PR_TRUE;
if (mDocument) {
mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ?
mDocumentObserverForNonDynamicContext.get() :
this);
mDocumentObserverForNonDynamicContext = nsnull;
mDocument->RemoveObserver(this);
}
return NS_OK;
}
@ -3624,10 +3495,6 @@ PresShell::RecreateFramesFor(nsIContent* aContent)
return NS_OK;
}
if (!mPresContext->IsDynamic()) {
return NS_OK;
}
// Don't call RecreateFramesForContent since that is not exported and we want
// to keep the number of entrypoints down.
@ -5159,9 +5026,6 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
nsresult
PresShell::ReconstructFrames(void)
{
if (!mPresContext || !mPresContext->IsDynamic()) {
return NS_OK;
}
nsAutoCauseReflowNotifier crNotifier(this);
mFrameConstructor->BeginUpdate();
nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();

View File

@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=396024
<window title="Mozilla Bug 396024" onload="run()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe src="data:text/html;charset=utf-8,&lt;body onload='window.parent.loadedChild()'&gt;"></iframe>
<iframe src="about:blank"/>
<script type="application/javascript">
<![CDATA[
var is = window.opener.wrappedJSObject.is;
@ -15,7 +16,7 @@ var ok = window.opener.wrappedJSObject.ok;
var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
var gWbp;
function printpreview() {
gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
var listener = {
onLocationChange: function(webProgress, request, location) { },
@ -37,12 +38,12 @@ function printpreview() {
prefs.setBoolPref('print.show_print_progress', false);
//XXX I would have thought this would work, instead I'm forced to use prefs service
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
}
@ -80,11 +81,11 @@ function run2() {
}
function run3() {
gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
ok(gWbp.doingPrintPreview, "Should be doing print preview");
window.loadedChild = null;
printpreview();
exitprintpreview();
setTimeout(run4, 0);
}
@ -93,9 +94,9 @@ function run4() {
window.loadedChild = function() { setTimeout(run5, 0); };
document.documentElement.getBoundingClientRect();
document.documentElement.appendChild(x);
gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore3");
ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
}
function run5() {

View File

@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=482976
<window title="Mozilla Bug 482976" onload="run1()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe src="data:text/html;charset=utf-8,&lt;body onload='window.parent.loadedChild()'&gt;&lt;q&gt;"></iframe>
<iframe src="about:blank"/>
<script type="application/javascript">
<![CDATA[
var is = window.opener.wrappedJSObject.is;
@ -15,7 +16,7 @@ var ok = window.opener.wrappedJSObject.ok;
var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
var gWbp;
function printpreview() {
gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
var listener = {
onLocationChange: function(webProgress, request, location) { },
@ -37,12 +38,12 @@ function printpreview() {
prefs.setBoolPref('print.show_print_progress', false);
//XXX I would have thought this would work, instead I'm forced to use prefs service
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
}

View File

@ -5,6 +5,7 @@
<window onload="runTests()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe height="200" width="600"></iframe>
<iframe height="200" width="600"></iframe>
<script type="application/javascript">
<![CDATA[
var is = window.opener.wrappedJSObject.is;
@ -17,7 +18,7 @@ var ctx2;
var counter = 0;
function printpreview() {
gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
var listener = {
onLocationChange: function(webProgress, request, location) { },
@ -38,13 +39,13 @@ function printpreview() {
.getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref('print.show_print_progress', false);
//XXX I would have thought this would work, instead I'm forced to use prefs service
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
gWbp.globalPrintSettings.showPrintProgress = false;
gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
prefs.clearUserPref('print.show_print_progress');
}
function exitprintpreview() {
window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
}
@ -104,11 +105,8 @@ function startTest1() {
window.frames[0].document.body.firstChild.innerHTML = "Print preview";
printpreview();
ctx1.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
ctx1.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
window.frames[0].document.body.firstChild.innerHTML = "Galley presentation";
window.frames[0].document.body.firstChild.innerHTML +=
"<div style='color: red;'>This is not for print preview!</div>";
window.frames[0].document.body.firstChild.lastChild.firstChild.data += " Really!";
// Add some elements.
addHTMLContent(window.frames[0].document.body.lastChild);
@ -121,11 +119,9 @@ function startTest1() {
}
function finalizeTest1() {
ctx2.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
ctx2.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
exitprintpreview();
ok(compareCanvases(), "Canvas should be the same!");
is(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers shouldn't have run yet!");
is(window.frames[0].counter, 0, "Timers shouldn't have run yet!");
counter = window.frames[0].counter;
// This timeout is needed so that we can check that timers do run after
// print preview.
@ -194,13 +190,13 @@ function compareFormElementPrint(el1, el2, equals) {
window.frames[0].document.body.firstChild.value =
window.frames[0].document.body.firstChild.getAttribute('value');
printpreview();
ctx1.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
ctx1.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
exitprintpreview();
window.frames[0].document.body.innerHTML = el2;
window.frames[0].document.body.firstChild.value =
window.frames[0].document.body.firstChild.getAttribute('value');
printpreview();
ctx2.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
ctx2.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
exitprintpreview();
is(compareCanvases(), equals,
"Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");

View File

@ -6187,7 +6187,8 @@ NS_IMETHODIMP nsBlockFrame::GetAccessible(nsIAccessible** aAccessible)
// Create special list bullet accessible
const nsStyleList* myList = GetStyleList();
nsAutoString bulletText;
if (myList->mListStyleImage || myList->mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
if (myList->GetListStyleImage() ||
myList->mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
myList->mListStyleType == NS_STYLE_LIST_STYLE_CIRCLE ||
myList->mListStyleType == NS_STYLE_LIST_STYLE_SQUARE) {
bulletText.Assign(PRUnichar(0x2022));; // Unicode bullet character
@ -6419,7 +6420,7 @@ nsBlockFrame::BulletIsEmpty() const
"should only care when we have an outside bullet");
const nsStyleList* list = GetStyleList();
return list->mListStyleType == NS_STYLE_LIST_STYLE_NONE &&
!list->mListStyleImage;
!list->GetListStyleImage();
}
// static

View File

@ -137,7 +137,7 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
{
nsFrame::DidSetStyleContext(aOldStyleContext);
imgIRequest *newRequest = GetStyleList()->mListStyleImage;
imgIRequest *newRequest = GetStyleList()->GetListStyleImage();
if (newRequest) {
@ -228,7 +228,7 @@ nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt,
const nsStyleList* myList = GetStyleList();
PRUint8 listStyleType = myList->mListStyleType;
if (myList->mListStyleImage && mImageRequest) {
if (myList->GetListStyleImage() && mImageRequest) {
PRUint32 status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
@ -1258,7 +1258,7 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
const nsStyleList* myList = GetStyleList();
nscoord ascent;
if (myList->mListStyleImage && mImageRequest) {
if (myList->GetListStyleImage() && mImageRequest) {
PRUint32 status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&

View File

@ -121,7 +121,7 @@
#include "nsBoxLayoutState.h"
#include "nsBlockFrame.h"
#include "nsDisplayList.h"
#include "nsIObjectLoadingContent.h"
#ifdef MOZ_SVG
#include "nsSVGIntegrationUtils.h"
#include "nsSVGEffects.h"

View File

@ -1322,22 +1322,12 @@ void
nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
// if we are printing, we need to get the correct nsIPluginInstance
// for THIS content node in order to call ->Print() on the right plugin
// first, we need to get the document
nsIDocument* doc = mContent->GetCurrentDoc();
if (!doc)
nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
if (!obj)
return;
// now we need to get the shell for the screen
// XXX assuming that the shell at zero will always be the screen one
nsIPresShell *shell = doc->GetPrimaryShell();
if (!shell)
return;
// then the shell can give us the screen frame for this content node
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
nsIFrame* frame = nsnull;
obj->GetPrintFrame(&frame);
if (!frame)
return;

View File

@ -60,10 +60,6 @@
class nsTextPaintStyle;
class PropertyProvider;
// This bit is set while the frame is registered as a blinking frame or if
// frame is within a non-dynamic PresContext.
#define TEXT_BLINK_ON_OR_PRINTING 0x20000000
// This state bit is set on frames that have some non-collapsed characters after
// reflow
#define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
@ -369,17 +365,9 @@ public:
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
PRBool aTrimAfter);
const nsTextFragment* GetFragment() const
{
return !(GetStateBits() & TEXT_BLINK_ON_OR_PRINTING) ?
mContent->GetText() : GetFragmentInternal();
}
protected:
virtual ~nsTextFrame();
const nsTextFragment* GetFragmentInternal() const;
nsIFrame* mNextContinuation;
// The key invariant here is that mContentOffset never decreases along
// a next-continuation chain. And of course mContentOffset is always <= the

View File

@ -165,9 +165,8 @@
#define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000
#define TEXT_WHITESPACE_FLAGS 0x18000000
// nsTextFrame.h has
// #define TEXT_BLINK_ON_OR_PRINTING 0x20000000
// This bit is set while the frame is registered as a blinking frame.
#define TEXT_BLINK_ON 0x20000000
// Set when this text frame is mentioned in the userdata for a textrun
#define TEXT_IN_TEXTRUN_USER_DATA 0x40000000
@ -484,7 +483,7 @@ nsTextFrameTextRunCache::Shutdown() {
PRInt32 nsTextFrame::GetContentEnd() const {
nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
return next ? next->GetContentOffset() : GetFragment()->GetLength();
return next ? next->GetContentOffset() : mContent->GetText()->GetLength();
}
PRInt32 nsTextFrame::GetInFlowContentLength() {
@ -500,7 +499,7 @@ PRInt32 nsTextFrame::GetInFlowContentLength() {
}
}
#endif //IBMBIDI
return GetFragment()->GetLength() - mContentOffset;
return mContent->TextLength() - mContentOffset;
}
// Smarter versions of XP_IS_SPACE.
@ -729,7 +728,7 @@ public:
PRInt32 GetContentEnd() {
return mEndFrame ? mEndFrame->GetContentOffset()
: mStartFrame->GetFragment()->GetLength();
: mStartFrame->GetContent()->GetText()->GetLength();
}
};
@ -947,7 +946,7 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState
if (textFrame) {
if (!aState->mSeenSpaceForLineBreakingOnThisLine) {
const nsTextFragment* frag = textFrame->GetFragment();
const nsTextFragment* frag = textFrame->GetContent()->GetText();
PRUint32 start = textFrame->GetContentOffset();
const void* text = frag->Is2b()
? static_cast<const void*>(frag->Get2b() + start)
@ -1272,7 +1271,7 @@ void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame)
{
NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow");
mMaxTextLength += aFrame->GetContentLength();
mDoubleByteText |= aFrame->GetFragment()->Is2b();
mDoubleByteText |= aFrame->GetContent()->GetText()->Is2b();
mLastFrame = aFrame;
mCommonAncestorWithLastFrame = aFrame->GetParent();
@ -1305,7 +1304,7 @@ HasTerminalNewline(const nsTextFrame* aFrame)
{
if (aFrame->GetContentLength() == 0)
return PR_FALSE;
const nsTextFragment* frag = aFrame->GetFragment();
const nsTextFragment* frag = aFrame->GetContent()->GetText();
return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n';
}
@ -1626,7 +1625,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
// Figure out what content is included in this flow.
nsIContent* content = f->GetContent();
const nsTextFragment* frag = f->GetFragment();
const nsTextFragment* frag = content->GetText();
PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset();
PRInt32 contentEnd = mappedFlow->GetContentEnd();
PRInt32 contentLength = contentEnd - contentStart;
@ -1855,7 +1854,7 @@ HasCompressedLeadingWhitespace(nsTextFrame* aFrame, const nsStyleText* aStyleTex
gfxSkipCharsIterator iter = aIterator;
PRInt32 frameContentOffset = aFrame->GetContentOffset();
const nsTextFragment* frag = aFrame->GetFragment();
const nsTextFragment* frag = aFrame->GetContent()->GetText();
while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) {
if (IsTrimmableSpace(frag, frameContentOffset, aStyleText))
return PR_TRUE;
@ -2223,7 +2222,7 @@ public:
PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
: mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull),
mTextStyle(aFrame->GetStyleText()),
mFrag(aFrame->GetFragment()),
mFrag(aFrame->GetContent()->GetText()),
mLineContainer(nsnull),
mFrame(aFrame), mStart(aStart), mTempIterator(aStart),
mTabWidths(nsnull),
@ -3409,11 +3408,6 @@ nsTextFrame::Init(nsIContent* aContent,
NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
"Bogus content!");
if (!PresContext()->IsDynamic()) {
AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
}
// Since our content has a frame now, this flag is no longer needed.
aContent->UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE);
// We're not a continuing frame.
@ -3498,11 +3492,6 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
nsIFrame* aPrevInFlow)
{
NS_ASSERTION(aPrevInFlow, "Must be a continuation!");
if (!PresContext()->IsDynamic()) {
AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
}
// NOTE: bypassing nsTextFrame::Init!!!
nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
@ -3515,7 +3504,7 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
aPrevInFlow->SetNextInFlow(this);
nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint();
NS_ASSERTION(mContentOffset < PRInt32(GetFragment()->GetLength()),
NS_ASSERTION(mContentOffset < PRInt32(aContent->GetText()->GetLength()),
"Creating ContinuingTextFrame, but there is no more content");
if (prev->GetStyleContext() != GetStyleContext()) {
// We're taking part of prev's text, and its style may be different
@ -3704,7 +3693,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsContinuingTextFrame)
nsTextFrame::~nsTextFrame()
{
if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic())
if (0 != (mState & TEXT_BLINK_ON))
{
nsBlinkTimer::RemoveBlinkFrame(this);
}
@ -3912,7 +3901,7 @@ nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
if ((0 != (mState & TEXT_BLINK_ON_OR_PRINTING)) && nsBlinkTimer::GetBlinkIsOff() &&
if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff() &&
PresContext()->IsDynamic() && !aBuilder->IsForEventDelivery())
return NS_OK;
@ -5246,7 +5235,7 @@ nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
if (!mTextRun)
return PR_FALSE;
TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_TRUE);
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_TRUE);
// Check whether there are nonskipped characters in the trimmmed range
return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
iter.ConvertOriginalToSkipped(trimmed.mStart);
@ -5313,7 +5302,7 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
if (!mTextRun)
return PR_FALSE;
TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_FALSE);
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_FALSE);
// A negative offset means "end of frame".
PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
@ -5428,7 +5417,7 @@ ClusterIterator::ClusterIterator(nsTextFrame* aTextFrame, PRInt32 aPosition,
mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
mFrag = aTextFrame->GetFragment();
mFrag = aTextFrame->GetContent()->GetText();
mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE);
PRInt32 textOffset = aTextFrame->GetContentOffset();
@ -5669,7 +5658,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
// Pass null for the line container. This will disable tab spacing, but that's
// OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = GetFragment();
const nsTextFragment* frag = mContent->GetText();
PropertyProvider provider(mTextRun, textStyle, frag, this,
iter, PR_INT32_MAX, nsnull, 0);
@ -5797,7 +5786,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
// OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = GetFragment();
const nsTextFragment* frag = mContent->GetText();
PropertyProvider provider(mTextRun, textStyle, frag, this,
iter, PR_INT32_MAX, nsnull, 0);
@ -6062,8 +6051,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
/////////////////////////////////////////////////////////////////////
// Clear out the reflow state flags in mState (without destroying
// the TEXT_BLINK_ON_OR_PRINTING bit). We also clear the whitespace flags
// because this can change whether the frame maps whitespace-only text or not.
// the TEXT_BLINK_ON bit). We also clear the whitespace flags because this
// can change whether the frame maps whitespace-only text or not.
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
// Temporarily map all possible content while we construct our new textrun.
@ -6085,14 +6074,14 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
nsLineLayout& lineLayout = *aReflowState.mLineLayout;
if (aReflowState.mFlags.mBlinks) {
if (0 == (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState |= TEXT_BLINK_ON_OR_PRINTING;
if (0 == (mState & TEXT_BLINK_ON)) {
mState |= TEXT_BLINK_ON;
nsBlinkTimer::AddBlinkFrame(aPresContext, this);
}
}
else {
if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState &= ~TEXT_BLINK_ON_OR_PRINTING;
if (0 != (mState & TEXT_BLINK_ON)) {
mState &= ~TEXT_BLINK_ON;
nsBlinkTimer::RemoveBlinkFrame(this);
}
}
@ -6107,7 +6096,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
PRUint32 flowEndInTextRun;
nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
gfxContext* ctx = aReflowState.rendContext->ThebesContext();
const nsTextFragment* frag = GetFragment();
const nsTextFragment* frag = mContent->GetText();
// DOM offsets of the text range we need to measure, after trimming
// whitespace, restricting to first-letter, and restricting preformatted text
@ -6527,7 +6516,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIRenderingContext* aRC)
PRUint32 trimmedStart = start.GetSkippedOffset();
const nsTextFragment* frag = GetFragment();
const nsTextFragment* frag = mContent->GetText();
TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE);
gfxSkipCharsIterator trimmedEndIter = start;
const nsStyleText* textStyle = GetStyleText();
@ -6664,7 +6653,7 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
// The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
gfxSkipCharsBuilder skipCharsBuilder;
nsTextFrame* textFrame;
const nsTextFragment* textFrag = GetFragment();
const nsTextFragment* textFrag = mContent->GetText();
PRUint32 keptCharsLength = 0;
PRUint32 validCharsLength = 0;
@ -6730,7 +6719,7 @@ void
nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const
{
// Get the frames text content
const nsTextFragment* frag = GetFragment();
const nsTextFragment* frag = mContent->GetText();
if (!frag) {
return;
}
@ -6790,7 +6779,7 @@ nsTextFrame::IsEmpty()
return PR_TRUE;
}
PRBool isEmpty = IsAllWhitespace(GetFragment(),
PRBool isEmpty = IsAllWhitespace(mContent->GetText(),
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
return isEmpty;
@ -6927,10 +6916,3 @@ nsTextFrame::IsAtEndOfLine() const
{
return (GetStateBits() & TEXT_END_OF_LINE) != 0;
}
const nsTextFragment*
nsTextFrame::GetFragmentInternal() const
{
return PresContext()->IsDynamic() ? mContent->GetText() :
nsLayoutUtils::GetTextFragmentForPrinting(this);
}

View File

@ -101,6 +101,12 @@ public:
virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
nsIContent* GetPosterImage() { return mPosterImage; }
// Returns PR_TRUE if we should display the poster. Note that once we show
// a video frame, the poster will never be displayed again.
PRBool ShouldDisplayPoster();
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif
@ -115,10 +121,6 @@ protected:
// when we're the frame for an audio element, or we've created a video
// element for a media which is audio-only.
PRBool HasVideoData();
// Returns PR_TRUE if we should display the poster. Note that once we show
// a video frame, the poster will never be displayed again.
PRBool ShouldDisplayPoster();
// Sets the mPosterImage's src attribute to be the video's poster attribute,
// if we're the frame for a video element. Only call on frames for video

View File

@ -158,7 +158,7 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
#include "nsPIDOMWindow.h"
#include "nsFocusManager.h"
#include "nsRange.h"
#include "nsCDefaultURIFixup.h"
#include "nsIURIFixup.h"
@ -439,9 +439,10 @@ static void DumpLayoutData(char* aTitleStr, char* aURLStr,
nsresult
nsPrintEngine::CommonPrint(PRBool aIsPrintPreview,
nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener) {
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc) {
nsresult rv = DoCommonPrint(aIsPrintPreview, aPrintSettings,
aWebProgressListener);
aWebProgressListener, aDoc);
if (NS_FAILED(rv)) {
if (aIsPrintPreview) {
SetIsCreatingPrintPreview(PR_FALSE);
@ -463,7 +464,8 @@ nsPrintEngine::CommonPrint(PRBool aIsPrintPreview,
nsresult
nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview,
nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener)
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc)
{
nsresult rv;
@ -540,7 +542,7 @@ nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview,
mPrt->mPrintObject = new nsPrintObject();
NS_ENSURE_TRUE(mPrt->mPrintObject, NS_ERROR_OUT_OF_MEMORY);
rv = mPrt->mPrintObject->Init(webContainer);
rv = mPrt->mPrintObject->Init(webContainer, aDoc, aIsPrintPreview);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(mPrt->mPrintDocList.AppendElement(mPrt->mPrintObject),
@ -550,11 +552,13 @@ nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview,
mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc;
// Build the "tree" of PrintObjects
nsCOMPtr<nsIDocShellTreeNode> parentAsNode(do_QueryInterface(webContainer));
nsCOMPtr<nsIDocShellTreeNode> parentAsNode =
do_QueryInterface(mPrt->mPrintObject->mDocShell);
BuildDocTree(parentAsNode, &mPrt->mPrintDocList, mPrt->mPrintObject);
// XXX This isn't really correct...
if (!mPrt->mPrintObject->mDocument->GetRootContent())
if (!mPrt->mPrintObject->mDocument ||
!mPrt->mPrintObject->mDocument->GetRootContent())
return NS_ERROR_GFX_PRINTER_STARTDOC;
// Create the linkage from the sub-docs back to the content element
@ -749,7 +753,8 @@ NS_IMETHODIMP
nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener)
{
return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener);
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener, doc);
}
NS_IMETHODIMP
@ -770,8 +775,13 @@ nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings,
return NS_ERROR_FAILURE;
}
NS_ENSURE_STATE(aChildDOMWin);
nsCOMPtr<nsIDOMDocument> doc;
aChildDOMWin->GetDocument(getter_AddRefs(doc));
NS_ENSURE_STATE(doc);
// Document is not busy -- go ahead with the Print Preview
return CommonPrint(PR_TRUE, aPrintSettings, aWebProgressListener);
return CommonPrint(PR_TRUE, aPrintSettings, aWebProgressListener, doc);
}
//----------------------------------------------------------------------------------
@ -1089,12 +1099,6 @@ nsPrintEngine::IsThereARangeSelection(nsIDOMWindow* aDOMWin)
PRBool
nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent)
{
NS_ASSERTION(aParent, "Pointer is null!");
nsCOMPtr<nsIPresShell> shell;
aParent->GetPresShell(getter_AddRefs(shell));
NS_ASSERTION(shell, "shell can't be null");
// See if the incoming doc is the root document
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(aParent));
if (!parentAsItem) return PR_FALSE;
@ -1114,13 +1118,12 @@ nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent)
PRBool isFrameSet = PR_FALSE;
// only check to see if there is a frameset if there is
// NO parent doc for this doc. meaning this parent is the root doc
if (shell) {
nsIDocument *doc = shell->GetDocument();
if (doc) {
nsIContent *rootContent = doc->GetRootContent();
if (rootContent) {
isFrameSet = HasFramesetChild(rootContent);
}
nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(aParent);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (doc) {
nsIContent *rootContent = doc->GetRootContent();
if (rootContent) {
isFrameSet = HasFramesetChild(rootContent);
}
}
return isFrameSet;
@ -1154,11 +1157,12 @@ nsPrintEngine::BuildDocTree(nsIDocShellTreeNode * aParentNode,
if (viewerFile) {
nsCOMPtr<nsIDocShell> childDocShell(do_QueryInterface(child));
nsCOMPtr<nsIDocShellTreeNode> childNode(do_QueryInterface(child));
nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(childDocShell);
nsPrintObject * po = new nsPrintObject();
nsresult rv = po->Init(childDocShell);
po->mParent = aPO;
nsresult rv = po->Init(childDocShell, doc, aPO->mPrintPreview);
if (NS_FAILED(rv))
NS_NOTREACHED("Init failed?");
po->mParent = aPO;
aPO->mKids.AppendElement(po);
aDocList->AppendElement(po);
BuildDocTree(childNode, aDocList, po);
@ -1220,7 +1224,16 @@ nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO,
// Recursively walk the content from the root item
// XXX Would be faster to enumerate the subdocuments, although right now
// nsIDocument doesn't expose quite what would be needed.
nsIContent *rootContent = aPO->mDocument->GetRootContent();
nsCOMPtr<nsIContentViewer> viewer;
aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer));
if (!viewer) return;
nsCOMPtr<nsIDOMDocument> domDoc;
viewer->GetDOMDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (!doc) return;
nsIContent* rootContent = doc->GetRootContent();
if (rootContent) {
MapContentForPO(aPO, rootContent);
} else {
@ -1313,7 +1326,6 @@ nsPrintEngine::MapContentForPO(nsPrintObject* aPO,
// XXX If a subdocument has no onscreen presentation, there will be no PO
// This is even if there should be a print presentation
if (po) {
po->mContent = aContent;
nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent));
// "frame" elements not in a frameset context should be treated
@ -1911,6 +1923,8 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
canCreateScrollbars = PR_FALSE;
}
NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext");
// create the PresContext
aPO->mPresContext = new nsRootPresContext(aPO->mDocument,
mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
@ -1991,6 +2005,13 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
float(mPrt->mPrintDC->AppUnitsPerDevPixel());
aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
if (mIsCreatingPrintPreview && documentIsTopLevel) {
mDocViewerPrint->SetPrintPreviewPresentation(aPO->mWindow,
aPO->mViewManager,
aPO->mPresContext,
aPO->mPresShell);
}
rv = aPO->mPresShell->InitialReflow(adjSize.width, adjSize.height);
NS_ENSURE_SUCCESS(rv, rv);
@ -2132,6 +2153,100 @@ nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus)
return PR_FALSE;
}
static already_AddRefed<nsIDOMNode>
GetEqualNodeInCloneTree(nsIDOMNode* aNode, nsIDocument* aDoc)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
// Selections in anonymous subtrees aren't supported.
if (content && content->IsInAnonymousSubtree()) {
return nsnull;
}
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node, nsnull);
nsTArray<PRInt32> indexArray;
nsINode* current = node;
NS_ENSURE_TRUE(current, nsnull);
while (current) {
nsINode* parent = current->GetNodeParent();
if (!parent) {
break;
}
PRInt32 index = parent->IndexOf(current);
NS_ENSURE_TRUE(index >= 0, nsnull);
indexArray.AppendElement(index);
current = parent;
}
NS_ENSURE_TRUE(current->IsNodeOfType(nsINode::eDOCUMENT), nsnull);
current = aDoc;
for (PRInt32 i = indexArray.Length() - 1; i >= 0; --i) {
current = current->GetChildAt(indexArray[i]);
NS_ENSURE_TRUE(current, nsnull);
}
nsCOMPtr<nsIDOMNode> result = do_QueryInterface(current);
return result.forget();
}
static nsresult CloneRangeToSelection(nsIDOMRange* aRange,
nsIDocument* aDoc,
nsISelection* aSelection)
{
PRBool collapsed = PR_FALSE;
aRange->GetCollapsed(&collapsed);
if (collapsed) {
return NS_OK;
}
nsCOMPtr<nsIDOMNode> startContainer, endContainer;
PRInt32 startOffset = -1, endOffset = -1;
aRange->GetStartContainer(getter_AddRefs(startContainer));
aRange->GetStartOffset(&startOffset);
aRange->GetEndContainer(getter_AddRefs(endContainer));
aRange->GetEndOffset(&endOffset);
NS_ENSURE_STATE(startContainer && endContainer);
nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
NS_ENSURE_STATE(newStart && newEnd);
nsCOMPtr<nsIDOMRange> range;
NS_NewRange(getter_AddRefs(range));
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = range->SetStart(newStart, startOffset);
NS_ENSURE_SUCCESS(rv, rv);
rv = range->SetEnd(newEnd, endOffset);
NS_ENSURE_SUCCESS(rv, rv);
return aSelection->AddRange(range);
}
static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc)
{
nsIPresShell* origShell = aOrigDoc->GetPrimaryShell();
nsIPresShell* shell = aDoc->GetPrimaryShell();
NS_ENSURE_STATE(origShell && shell);
nsCOMPtr<nsISelection> origSelection =
origShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
nsCOMPtr<nsISelection> selection =
shell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
NS_ENSURE_STATE(origSelection && selection);
PRInt32 rangeCount = 0;
origSelection->GetRangeCount(&rangeCount);
for (PRInt32 i = 0; i < rangeCount; ++i) {
nsCOMPtr<nsIDOMRange> range;
origSelection->GetRangeAt(i, getter_AddRefs(range));
if (range) {
CloneRangeToSelection(range, aDoc, selection);
}
}
return NS_OK;
}
//-------------------------------------------------------
nsresult
nsPrintEngine::DoPrint(nsPrintObject * aPO)
@ -2195,6 +2310,8 @@ nsPrintEngine::DoPrint(nsPrintObject * aPO)
GetDisplayTitleAndURL(aPO, &docTitleStr, &docURLStr, eDocTitleDefBlank);
if (nsIPrintSettings::kRangeSelection == printRangeType) {
CloneSelection(aPO->mDocument->GetOriginalDocument(), aPO->mDocument);
poPresContext->SetIsRenderingOnlySelection(PR_TRUE);
// temporarily creating rendering context
// which is needed to dinf the selection frames
@ -2796,8 +2913,10 @@ nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO,
return nsnull;
}
nsCOMPtr<nsIDOMWindow> domWin(do_GetInterface(aPO->mDocShell));
if (domWin && domWin == aDOMWin) {
nsCOMPtr<nsIDOMDocument> domDoc;
aDOMWin->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) {
return aPO;
}
@ -2901,7 +3020,8 @@ nsPrintEngine::EnablePOsForPrinting()
//
// XXX this is sort of a hack right here to make the page
// not try to reposition itself when printing selection
nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell);
nsCOMPtr<nsIDOMWindow> domWin =
do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
if (!IsThereARangeSelection(domWin)) {
printRangeType = nsIPrintSettings::kRangeAllPages;
mPrt->mPrintSettings->SetPrintRange(printRangeType);
@ -2948,7 +3068,8 @@ nsPrintEngine::EnablePOsForPrinting()
//
// XXX this is sort of a hack right here to make the page
// not try to reposition itself when printing selection
nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell);
nsCOMPtr<nsIDOMWindow> domWin =
do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
if (!IsThereARangeSelection(domWin)) {
printRangeType = nsIPrintSettings::kRangeAllPages;
mPrt->mPrintSettings->SetPrintRange(printRangeType);

View File

@ -227,10 +227,12 @@ public:
protected:
nsresult CommonPrint(PRBool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener);
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc);
nsresult DoCommonPrint(PRBool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aWebProgressListener);
nsIWebProgressListener* aWebProgressListener,
nsIDOMDocument* aDoc);
void FirePrintCompletionEvent();
static nsresult GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO,

View File

@ -39,6 +39,12 @@
#include "nsIContentViewer.h"
#include "nsIDOMDocument.h"
#include "nsContentUtils.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsPIDOMWindow.h"
#include "nsGkAtoms.h"
#include "nsComponentManagerUtils.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellTreeItem.h"
//---------------------------------------------------
//-- nsPrintObject Class Impl
@ -65,23 +71,49 @@ nsPrintObject::~nsPrintObject()
//------------------------------------------------------------------
// Resets PO by destroying the presentation
nsresult
nsPrintObject::Init(nsIDocShell* aDocShell)
nsPrintObject::Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
PRBool aPrintPreview)
{
mDocShell = aDocShell;
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsresult rv;
nsCOMPtr<nsIContentViewer> viewer;
rv = mDocShell->GetContentViewer(getter_AddRefs(viewer));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> doc;
viewer->GetDOMDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
mDocument = do_QueryInterface(doc);
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
mPrintPreview = aPrintPreview;
if (mPrintPreview || mParent) {
mDocShell = aDocShell;
} else {
nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(aDocShell);
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(aDocShell);
PRInt32 itemType = 0;
item->GetItemType(&itemType);
// Create a container docshell for printing.
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIDocShellTreeItem> newItem = do_QueryInterface(mDocShell);
newItem->SetItemType(itemType);
newItem->SetTreeOwner(owner);
}
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(mDocShell);
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
NS_ENSURE_STATE(viewer);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
NS_ENSURE_STATE(doc);
if (mParent) {
nsCOMPtr<nsPIDOMWindow> window = doc->GetWindow();
if (window) {
mContent = do_QueryInterface(window->GetFrameElementInternal());
}
mDocument = doc;
return NS_OK;
}
mDocument = doc->CreateStaticClone(mDocShell);
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(mDocument);
NS_ENSURE_STATE(clonedDOMDoc);
viewer->SetDOMDocument(clonedDOMDoc);
return NS_OK;
}

View File

@ -62,7 +62,8 @@ public:
~nsPrintObject(); // non-virtual
// Methods
nsresult Init(nsIDocShell* aDocShell);
nsresult Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
PRBool aPrintPreview);
PRBool IsPrintable() { return !mDontPrint; }
void DestroyPresentation();
@ -76,7 +77,7 @@ public:
nsCOMPtr<nsIViewManager> mViewManager;
nsCOMPtr<nsIWidget> mWindow;
nsIContent* mContent;
nsCOMPtr<nsIContent> mContent;
PrintObjectType mFrameType;
nsTArray<nsPrintObject*> mKids;
@ -86,7 +87,7 @@ public:
PRPackedBool mPrintAsIs;
PRPackedBool mSharedPresShell;
PRPackedBool mInvisible; // Indicates PO is set to not visible by CSS
PRPackedBool mPrintPreview;
float mShrinkRatio;
float mZoomRatio;

View File

@ -2269,12 +2269,12 @@ nsComputedDOMStyle::GetListStyleImage(nsIDOMCSSValue** aValue)
const nsStyleList* list = GetStyleList();
if (!list->mListStyleImage) {
if (!list->GetListStyleImage()) {
val->SetIdent(eCSSKeyword_none);
} else {
nsCOMPtr<nsIURI> uri;
if (list->mListStyleImage) {
list->mListStyleImage->GetURI(getter_AddRefs(uri));
if (list->GetListStyleImage()) {
list->GetListStyleImage()->GetURI(getter_AddRefs(uri));
}
val->SetURI(uri);
}

View File

@ -76,6 +76,15 @@
#include "nsCSSKeywords.h"
#include "nsCSSProps.h"
#include "nsTArray.h"
#include "nsContentUtils.h"
#define NS_SET_IMAGE_REQUEST(method_, context_, request_) \
if ((context_)->PresContext()->IsDynamic()) { \
method_(request_); \
} else { \
nsCOMPtr<imgIRequest> req = nsContentUtils::GetStaticRequest(request_); \
method_(req); \
}
/*
* For storage of an |nsRuleNode|'s children in a PLDHashTable.
@ -607,7 +616,8 @@ static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
}
// -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
static void SetStyleImageToImageRect(const nsCSSValue& aValue,
static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
const nsCSSValue& aValue,
nsStyleImage& aResult)
{
NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Function &&
@ -619,7 +629,9 @@ static void SetStyleImageToImageRect(const nsCSSValue& aValue,
// <uri>
if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
aResult.SetImageData(arr->Item(1).GetImageValue());
NS_SET_IMAGE_REQUEST(aResult.SetImageData,
aStyleContext,
arr->Item(1).GetImageValue())
} else {
NS_WARNING("nsCSSValue::Image::Image() failed?");
}
@ -645,11 +657,13 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
switch (aValue.GetUnit()) {
case eCSSUnit_Image:
aResult.SetImageData(aValue.GetImageValue());
NS_SET_IMAGE_REQUEST(aResult.SetImageData,
aStyleContext,
aValue.GetImageValue())
break;
case eCSSUnit_Function:
if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
SetStyleImageToImageRect(aValue, aResult);
SetStyleImageToImageRect(aStyleContext, aValue, aResult);
} else {
NS_NOTREACHED("-moz-image-rect() is the only expected function");
}
@ -4874,7 +4888,9 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
// the image
if (eCSSUnit_Image == arr->Item(0).GetUnit()) {
border->SetBorderImage(arr->Item(0).GetImageValue());
NS_SET_IMAGE_REQUEST(border->SetBorderImage,
aContext,
arr->Item(0).GetImageValue())
}
// the numbers saying where to split the image
@ -4937,7 +4953,8 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
border->mBorderImageHFill = parentBorder->mBorderImageHFill;
border->mBorderImageVFill = parentBorder->mBorderImageVFill;
border->mHaveBorderImageWidth = parentBorder->mHaveBorderImageWidth;
border->SetBorderImage(parentBorder->GetBorderImage());
NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
parentBorder->GetBorderImage())
}
COMPUTE_END_RESET(Border, border)
@ -5094,15 +5111,19 @@ nsRuleNode::ComputeListData(void* aStartStruct,
// list-style-image: url, none, inherit
if (eCSSUnit_Image == listData.mImage.GetUnit()) {
list->mListStyleImage = listData.mImage.GetImageValue();
NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
aContext,
listData.mImage.GetImageValue())
}
else if (eCSSUnit_None == listData.mImage.GetUnit() ||
eCSSUnit_Initial == listData.mImage.GetUnit()) {
list->mListStyleImage = nsnull;
list->SetListStyleImage(nsnull);
}
else if (eCSSUnit_Inherit == listData.mImage.GetUnit()) {
canStoreInRuleTree = PR_FALSE;
list->mListStyleImage = parentList->mListStyleImage;
NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
aContext,
parentList->GetListStyleImage())
}
// list-style-position: enum, inherit, initial
@ -5382,8 +5403,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
}
data.mType = type;
if (type == eStyleContentType_Image) {
data.mContent.mImage = value.GetImageValue();
NS_IF_ADDREF(data.mContent.mImage);
NS_SET_IMAGE_REQUEST(data.SetImage, aContext, value.GetImageValue());
}
else if (type <= eStyleContentType_Attr) {
value.GetStringValue(buffer);

View File

@ -66,6 +66,7 @@
#include "nsCSSValue.h"
#include "nsStyleTransformMatrix.h"
#include "nsAlgorithm.h"
#include "imgIRequest.h"
class nsIFrame;
class imgIRequest;
@ -915,7 +916,7 @@ protected:
PRUint8 mBorderStyle[4]; // [reset] See nsStyleConsts.h
nscolor mBorderColor[4]; // [reset] the colors to use for a simple border. not used
// if -moz-border-colors is specified
private:
nsCOMPtr<imgIRequest> mBorderImage; // [reset]
// Cache used by callers for border-image painting
@ -1033,9 +1034,17 @@ struct nsStyleList {
#endif
static PRBool ForceCompare() { return PR_FALSE; }
imgIRequest* GetListStyleImage() const { return mListStyleImage; }
void SetListStyleImage(imgIRequest* aReq)
{
mListStyleImage = aReq;
}
PRUint8 mListStyleType; // [inherited] See nsStyleConsts.h
PRUint8 mListStylePosition; // [inherited]
PRUint8 mListStylePosition; // [inherited]
private:
nsCOMPtr<imgIRequest> mListStyleImage; // [inherited]
public:
nsRect mImageRegion; // [inherited] the rect to use within an image
};
@ -1452,6 +1461,12 @@ struct nsStyleContentData {
PRBool operator!=(const nsStyleContentData& aOther) const {
return !(*this == aOther);
}
void SetImage(imgIRequest* aRequest)
{
NS_ASSERTION(mType == eStyleContentType_Image, "Wrong type!");
NS_IF_ADDREF(mContent.mImage = aRequest);
}
private:
nsStyleContentData(const nsStyleContentData&); // not to be implemented
};

View File

@ -54,7 +54,6 @@
#include "gfxMatrix.h"
#include "gfxPlatform.h"
#include "gfxTextRunWordCache.h"
#include "nsTextFrame.h"
struct CharacterPosition {
gfxPoint pos;
@ -295,10 +294,6 @@ nsSVGGlyphFrame::Init(nsIContent* aContent,
"trying to construct an SVGGlyphFrame for wrong content element");
#endif /* DEBUG */
if (!PresContext()->IsDynamic()) {
AddStateBits(NS_STATE_SVG_PRINTING);
}
return nsSVGGlyphFrameBase::Init(aContent, aParent, aPrevInFlow);
}
@ -637,7 +632,7 @@ PRBool
nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
{
nsAutoString characterData;
GetFragment()->AppendTo(characterData);
mContent->AppendTextTo(characterData);
if (mWhitespaceHandling & COMPRESS_WHITESPACE) {
PRBool trimLeadingWhitespace, trimTrailingWhitespace;
@ -841,7 +836,7 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
// The selection ranges are relative to the uncompressed text in
// the content element. We'll need the text fragment:
const nsTextFragment* fragment = GetFragment();
const nsTextFragment *fragment = mContent->GetText();
NS_ASSERTION(fragment, "no text");
// get the selection details
@ -1122,7 +1117,7 @@ PRUint32
nsSVGGlyphFrame::GetNumberOfChars()
{
if (mWhitespaceHandling == PRESERVE_WHITESPACE)
return GetFragment()->GetLength();
return mContent->TextLength();
nsAutoString text;
GetCharacterData(text);

View File

@ -208,11 +208,6 @@ protected:
nscolor *foreground, nscolor *background);
float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars);
gfxFloat GetBaselineOffset(PRBool aForceGlobalTransform);
const nsTextFragment* GetFragment() const
{
return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?
mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this);
}
// Used to support GetBBoxContribution by making GetConvasTM use this as the
// parent transform instead of the real CanvasTM.

View File

@ -95,9 +95,6 @@ class nsSVGDisplayContainerFrame;
#define NS_STATE_SVG_PROPAGATE_TRANSFORM 0x00800000
// nsSVGGlyphFrame uses this when the frame is within a non-dynamic PresContext.
#define NS_STATE_SVG_PRINTING 0x01000000
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/

View File

@ -279,7 +279,7 @@ nsImageBoxFrame::UpdateImage()
if (!(appearance && nsBox::gTheme &&
nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) {
// get the list-style-image
imgIRequest *styleRequest = GetStyleList()->mListStyleImage;
imgIRequest *styleRequest = GetStyleList()->GetListStyleImage();
if (styleRequest) {
styleRequest->Clone(mListener, getter_AddRefs(mImageRequest));
}
@ -417,8 +417,8 @@ nsImageBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
nsCOMPtr<nsIURI> oldURI, newURI;
if (mImageRequest)
mImageRequest->GetURI(getter_AddRefs(oldURI));
if (myList->mListStyleImage)
myList->mListStyleImage->GetURI(getter_AddRefs(newURI));
if (myList->GetListStyleImage())
myList->GetListStyleImage()->GetURI(getter_AddRefs(newURI));
PRBool equal;
if (newURI == oldURI || // handles null==null
(newURI && oldURI &&

View File

@ -2157,7 +2157,7 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, PRBool aUseCont
else {
// Obtain the URL from the style context.
aAllowImageRegions = PR_TRUE;
styleRequest = aStyleContext->GetStyleList()->mListStyleImage;
styleRequest = aStyleContext->GetStyleList()->GetListStyleImage();
if (!styleRequest)
return NS_OK;
nsCOMPtr<nsIURI> uri;

View File

@ -52,7 +52,7 @@ interface nsIPrincipal;
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(c0c9f606-19d6-4ed1-8486-6cae2fe0a6a4)]
[scriptable, uuid(ebde51c9-cc11-4b6a-99c3-d7f568c7481b)]
interface imgIRequest : nsIRequest
{
/**
@ -173,5 +173,11 @@ interface imgIRequest : nsIRequest
*/
void unlockImage();
/**
* If this request is for an animated image, the method creates a new
* request which contains the current frame of the image.
* Otherwise returns the same request.
*/
imgIRequest getStaticRequest();
};

View File

@ -56,7 +56,9 @@ CPPSRCS = \
imgLoader.cpp \
imgRequest.cpp \
imgRequestProxy.cpp \
imgTools.cpp
imgTools.cpp \
imgContainerRequest.cpp \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,280 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "imgContainerRequest.h"
#include "ImageErrors.h"
#include "imgRequest.h"
NS_IMPL_ISUPPORTS2(imgContainerRequest, imgIRequest, nsIRequest)
imgContainerRequest::imgContainerRequest(imgIContainer* aImage,
nsIURI* aURI,
PRUint32 aImageStatus,
PRUint32 aState,
nsIPrincipal* aPrincipal)
: mImage(aImage), mURI(aURI), mPrincipal(aPrincipal), mImageStatus(aImageStatus),
mState(aState), mLocksHeld(0)
{
#ifdef DEBUG
PRUint32 numFrames = 0;
if (aImage) {
aImage->GetNumFrames(&numFrames);
}
NS_ABORT_IF_FALSE(!aImage || numFrames == 1,
"Shouldn't have image with more than one frame!");
#endif
}
imgContainerRequest::~imgContainerRequest()
{
if (mImage) {
while (mLocksHeld) {
UnlockImage();
}
}
}
NS_IMETHODIMP
imgContainerRequest::GetName(nsACString& aName)
{
aName.Truncate();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::IsPending(PRBool* _retval)
{
*_retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetStatus(nsresult* aStatus)
{
*aStatus = NS_OK;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::Cancel(nsresult aStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::Suspend()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::Resume()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetLoadGroup(nsILoadGroup** aLoadGroup)
{
*aLoadGroup = nsnull;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetLoadFlags(nsLoadFlags* aLoadFlags)
{
*aLoadFlags = LOAD_NORMAL;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::SetLoadFlags(nsLoadFlags aLoadFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetImage(imgIContainer** aImage)
{
NS_IF_ADDREF(*aImage = mImage);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetImageStatus(PRUint32* aImageStatus)
{
*aImageStatus = mImageStatus;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetURI(nsIURI** aURI)
{
NS_IF_ADDREF(*aURI = mURI);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetDecoderObserver(imgIDecoderObserver** aDecoderObserver)
{
NS_IF_ADDREF(*aDecoderObserver = mObserver);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetMimeType(char** aMimeType)
{
*aMimeType = nsnull;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::Clone(imgIDecoderObserver* aObserver, imgIRequest** _retval)
{
imgContainerRequest* req =
new imgContainerRequest(mImage, mURI, mImageStatus, mState, mPrincipal);
if (!req) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*_retval = req);
req->mObserver = aObserver;
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(aObserver);
// Keep these notifications in sync with imgRequest::NotifyProxyListener!
// OnStartRequest
if (req->mState & stateRequestStarted)
aObserver->OnStartRequest(req);
// OnStartContainer
if (req->mState & stateHasSize)
aObserver->OnStartContainer(req, req->mImage);
// OnStartDecode
if (req->mState & stateDecodeStarted)
aObserver->OnStartDecode(req);
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes = 0;
if (req->mImage)
req->mImage->GetNumFrames(&nframes);
if (nframes > 0) {
PRUint32 frame;
req->mImage->GetCurrentFrameIndex(&frame);
aObserver->OnStartFrame(req, frame);
// OnDataAvailable
// XXX - Should only send partial rects here, but that needs to
// wait until we fix up the observer interface
nsIntRect r;
req->mImage->GetCurrentFrameRect(r);
aObserver->OnDataAvailable(req, frame, &r);
if (req->mState & stateRequestStopped)
aObserver->OnStopFrame(req, frame);
}
// Reseting image animation isn't needed here.
if (req->mState & stateRequestStopped) {
aObserver->OnStopContainer(req, req->mImage);
aObserver->OnStopDecode(req,
imgRequest::GetResultFromImageStatus(req->mImageStatus),
nsnull);
aObserver->OnStopRequest(req, PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetImagePrincipal(nsIPrincipal** aImagePrincipal)
{
NS_IF_ADDREF(*aImagePrincipal = mPrincipal);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::CancelAndForgetObserver(nsresult aStatus)
{
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::RequestDecode()
{
return mImage ? mImage->RequestDecode() : NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::LockImage()
{
if (mImage) {
++mLocksHeld;
return mImage->LockImage();
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::UnlockImage()
{
if (mImage) {
NS_ABORT_IF_FALSE(mLocksHeld > 0, "calling unlock but no locks!");
--mLocksHeld;
return mImage->UnlockImage();
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetStaticRequest(imgIRequest** aReturn)
{
NS_ADDREF(*aReturn = this);
return NS_OK;
}

View File

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef imgContainerRequest_h__
#define imgContainerRequest_h__
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
class imgContainerRequest : public imgIRequest
{
public:
imgContainerRequest(imgIContainer* aImage,
nsIURI* aURI,
PRUint32 aImageStatus,
PRUint32 aState,
nsIPrincipal* aPrincipal);
virtual ~imgContainerRequest();
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
protected:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<imgIDecoderObserver> mObserver;
PRUint32 mImageStatus;
PRUint32 mState;
PRUint32 mLocksHeld;
};
#endif

View File

@ -45,7 +45,6 @@
#include "imgContainer.h"
#include "imgILoader.h"
#include "ImageErrors.h"
#include "ImageLogging.h"
#include "netCore.h"
@ -255,6 +254,8 @@ nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
{
nsCOMPtr<imgIRequest> kungFuDeathGrip(proxy);
// Keep these notifications in sync with imgContainerRequest::Clone!
// OnStartRequest
if (mState & stateRequestStarted)
proxy->OnStartRequest(nsnull, nsnull);
@ -305,18 +306,6 @@ nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
return NS_OK;
}
nsresult imgRequest::GetResultFromImageStatus(PRUint32 aStatus) const
{
nsresult rv = NS_OK;
if (aStatus & imgIRequest::STATUS_ERROR)
rv = NS_IMAGELIB_ERROR_FAILURE;
else if (aStatus & imgIRequest::STATUS_LOAD_COMPLETE)
rv = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
return rv;
}
void imgRequest::Cancel(nsresult aStatus)
{
/* The Cancel() method here should only be called by this class. */

View File

@ -59,6 +59,8 @@
#include "nsString.h"
#include "nsTObserverArray.h"
#include "nsWeakReference.h"
#include "ImageErrors.h"
#include "imgIRequest.h"
class imgCacheValidator;
@ -118,7 +120,14 @@ public:
nsresult LockImage();
nsresult UnlockImage();
nsresult RequestDecode();
static nsresult GetResultFromImageStatus(PRUint32 aStatus)
{
if (aStatus & imgIRequest::STATUS_ERROR)
return NS_IMAGELIB_ERROR_FAILURE;
if (aStatus & imgIRequest::STATUS_LOAD_COMPLETE)
return NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
return NS_OK;
}
private:
friend class imgCacheEntry;
friend class imgRequestProxy;
@ -131,7 +140,7 @@ private:
mLoadTime = PR_Now();
}
inline PRUint32 GetImageStatus() const { return mImageStatus; }
inline nsresult GetResultFromImageStatus(PRUint32 aStatus) const;
inline PRUint32 GetState() const { return mState; }
void Cancel(nsresult aStatus);
nsresult GetURI(nsIURI **aURI);
nsresult GetKeyURI(nsIURI **aURI);

View File

@ -53,7 +53,7 @@
#include "ImageLogging.h"
#include "nspr.h"
#include "imgContainerRequest.h"
NS_IMPL_ISUPPORTS4(imgRequestProxy, imgIRequest, nsIRequest,
nsISupportsPriority, nsISecurityInfoProvider)
@ -673,3 +673,47 @@ void imgRequestProxy::NullOutListener()
mListener = nsnull;
}
}
NS_IMETHODIMP
imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
{
*aReturn = nsnull;
nsCOMPtr<imgIContainer> img, currentFrame;
GetImage(getter_AddRefs(img));
if (img) {
PRBool animated = PR_FALSE;
nsresult rv = img->GetAnimated(&animated);
if (NS_SUCCEEDED(rv) && !animated) {
NS_ADDREF(*aReturn = this);
return NS_OK;
}
PRInt32 w = 0;
PRInt32 h = 0;
img->GetWidth(&w);
img->GetHeight(&h);
nsIntRect rect(0, 0, w, h);
img->ExtractFrame(imgIContainer::FRAME_CURRENT, rect,
imgIContainer::FLAG_SYNC_DECODE,
getter_AddRefs(currentFrame));
}
nsCOMPtr<nsIURI> uri;
GetURI(getter_AddRefs(uri));
PRUint32 imageStatus = 0;
GetImageStatus(&imageStatus);
nsCOMPtr<nsIPrincipal> principal;
GetImagePrincipal(getter_AddRefs(principal));
imgContainerRequest* req =
new imgContainerRequest(currentFrame, uri, imageStatus,
mOwner ? mOwner->GetState() : 0,
principal);
if (!req) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aReturn = req);
return NS_OK;
}

View File

@ -161,7 +161,7 @@
<constructor>
<![CDATA[
var print = PrintUtils.getWebBrowserPrint();
var print = PrintUtils.getPrintPreview();
this.mTotalPages.value = print.printPreviewNumPages;
this.mPageTextBox.max = print.printPreviewNumPages;
@ -236,7 +236,7 @@
<parameter name="aHomeOrEnd"/>
<body>
<![CDATA[
var print = PrintUtils.getWebBrowserPrint();
var print = PrintUtils.getPrintPreview();
// we use only one of aHomeOrEnd, aDirection, or aPageNum
if (aHomeOrEnd)
@ -367,7 +367,7 @@
<method name="updateToolbar">
<body>
<![CDATA[
var print = PrintUtils.getWebBrowserPrint();
var print = PrintUtils.getPrintPreview();
var settings = PrintUtils.getPrintSettings();
var isPortrait = settings.orientation == Components.interfaces.nsIPrintSettings.kPortraitOrientation;

View File

@ -141,9 +141,9 @@ var PrintUtils = {
// this tells us whether we should continue on with PP or
// wait for the callback via the observer
if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null)
this.enterPrintPreview();
this.enterPrintPreview(aWindow);
} catch (e) {
this.enterPrintPreview();
this.enterPrintPreview(aWindow);
}
},
@ -154,6 +154,14 @@ var PrintUtils = {
.getInterface(Components.interfaces.nsIWebBrowserPrint);
},
getPrintPreview: function() {
if (this._printPreviewTab) {
var docShell = getPPBrowser().getBrowserForTab(this._printPreviewTab).docShell;
return docShell.printPreview;
}
return null;
},
////////////////////////////////////////
// "private" methods. Don't use them. //
////////////////////////////////////////
@ -219,6 +227,9 @@ var PrintUtils = {
}
},
_originalTab: null,
_printPreviewTab: null,
enterPrintPreview: function ()
{
gFocusedElement = document.commandDispatcher.focusedElement;
@ -229,11 +240,29 @@ var PrintUtils = {
ZoomManager.reset();
}
var webBrowserPrint = this.getWebBrowserPrint();
var printSettings = this.getPrintSettings();
var webBrowserPrint;
var printSettings = this.getPrintSettings();
var tabbrowser = getPPBrowser();
var contentWindow = null;
if (tabbrowser) {
if (this._printPreviewTab) {
contentWindow =
tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow;
} else {
this._originalTab = tabbrowser.mCurrentTab;
contentWindow = window.content
this._printPreviewTab = tabbrowser.loadOneTab("about:blank", null, null,
null, true, false);
}
}
try {
webBrowserPrint.printPreview(printSettings, null, this._webProgressPP.value);
webBrowserPrint = this.getPrintPreview();
webBrowserPrint.printPreview(printSettings, contentWindow,
this._webProgressPP.value);
} catch (e) {
this._printPreviewTab = null;
this._originalTab = null;
if (typeof ZoomManager == "object")
ZoomManager.zoom = this._originalZoomValue;
// Pressing cancel is expressed as an NS_ERROR_ABORT return value,
@ -249,6 +278,9 @@ var PrintUtils = {
var browser = getPPBrowser();
if (browser)
browser.collapsed = false;
tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow.focus();
tabbrowser.selectedTab = this._printPreviewTab;
return;
}
@ -274,7 +306,8 @@ var PrintUtils = {
// disable chrome shortcuts...
window.addEventListener("keypress", this.onKeyPressPP, true);
window.content.focus();
tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow.focus();
tabbrowser.selectedTab = this._printPreviewTab;
// on Enter PP Call back
if (this._onEnterPP) {
@ -293,6 +326,15 @@ var PrintUtils = {
var webBrowserPrint = this.getWebBrowserPrint();
webBrowserPrint.exitPrintPreview();
var tabbrowser = getPPBrowser();
if (tabbrowser) {
tabbrowser.removeTab(this._printPreviewTab);
tabbrowser.selectedTab = this._originalTab;
this._originalTab = null;
this._printPreviewTab = null;
}
if (typeof ZoomManager == "object")
ZoomManager.zoom = this._originalZoomValue;

View File

@ -468,8 +468,10 @@ NS_IMETHODIMP nsDeviceContextSpecWin::Init(nsIWidget* aWidget,
HGLOBAL hDevNames = NULL;
// Get the Print Name to be used
PRUnichar * printerName;
mPrintSettings->GetPrinterName(&printerName);
PRUnichar * printerName = nsnull;
if (mPrintSettings) {
mPrintSettings->GetPrinterName(&printerName);
}
// If there is no name then use the default printer
if (!printerName || (printerName && !*printerName)) {
@ -512,8 +514,10 @@ NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface
nsRefPtr<gfxASurface> newSurface;
PRInt16 outputFormat;
mPrintSettings->GetOutputFormat(&outputFormat);
PRInt16 outputFormat = 0;
if (mPrintSettings) {
mPrintSettings->GetOutputFormat(&outputFormat);
}
if (outputFormat == nsIPrintSettings::kOutputFormatPDF) {
nsXPIDLString filename;
@ -538,6 +542,7 @@ NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface
newSurface = new gfxPDFSurface(stream, gfxSize(width, height));
} else {
if (mDevMode) {
NS_WARN_IF_FALSE(mDriverName, "No driver!");
HDC dc = ::CreateDCW(mDriverName, mDeviceName, NULL, mDevMode);
// have this surface take over ownership of this DC