author | Julian Viereck <jviereck.dev@gmail.com> |
Tue, 04 Sep 2012 16:29:27 +0300 | |
changeset 107568 | 84317c2f199c22a56ee39c86471d537d2a9de78d |
parent 107567 | d7a64a0020698c94b814037a525fc15ea59c5779 |
child 107569 | 9404e57a5ce6000a4d8d9af1d0f7d9b6db6f45f3 |
push id | 15113 |
push user | rocallahan@mozilla.com |
push date | Thu, 20 Sep 2012 04:14:13 +0000 |
treeherder | mozilla-inbound@84317c2f199c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 468568 |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsDataDocumentContentPolicy.cpp +++ b/content/base/src/nsDataDocumentContentPolicy.cpp @@ -57,18 +57,21 @@ nsDataDocumentContentPolicy::ShouldLoad( // DTDs are always OK to load if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) { return NS_OK; } // Nothing else is OK to load for data documents if (doc->IsLoadedAsData()) { - *aDecision = nsIContentPolicy::REJECT_TYPE; - return NS_OK; + // ...but let static (print/print preview) documents to load fonts. + if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) { + *aDecision = nsIContentPolicy::REJECT_TYPE; + return NS_OK; + } } if (doc->IsBeingUsedAsImage()) { // We only allow SVG images to load content from URIs that are local and // also satisfy one of the following conditions: // - URI inherits security context, e.g. data URIs // OR // - URI loadable by subsumers, e.g. blob URIs
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -122,16 +122,17 @@ #include "nsIJSContextStack.h" #include "nsIXPConnect.h" #include "nsCycleCollector.h" #include "nsCCUncollectableMarker.h" #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" #include "nsICategoryManager.h" #include "nsIDocumentLoaderFactory.h" +#include "nsIDocumentLoader.h" #include "nsIContentViewer.h" #include "nsIXMLContentSink.h" #include "nsIXULDocument.h" #include "nsIPrompt.h" #include "nsIPropertyBag2.h" #include "nsIDOMPageTransitionEvent.h" #include "nsFrameLoader.h" #include "nsEscape.h" @@ -7623,18 +7624,25 @@ nsDocument::CloneDocHelper(nsDocument* c // Set URI/principal clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI()); // Must set the principal first, since SetBaseURI checks it. clone->SetPrincipal(NodePrincipal()); clone->mDocumentBaseURI = mDocumentBaseURI; if (mCreatingStaticClone) { + nsCOMPtr<nsILoadGroup> loadGroup; + + // |mDocumentContainer| is the container of the document that is being + // created and not the original container. See CreateStaticClone function(). + nsCOMPtr<nsIDocumentLoader> docLoader = do_QueryReferent(mDocumentContainer); + if (docLoader) { + docLoader->GetLoadGroup(getter_AddRefs(loadGroup)); + } 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()); } }
--- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -428,17 +428,17 @@ protected: unsigned mPrintPreviewZoomed : 1; // These data members support delayed printing when the document is loading unsigned mPrintIsPending : 1; unsigned mPrintDocIsFullyLoaded : 1; nsCOMPtr<nsIPrintSettings> mCachedPrintSettings; nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner; - nsCOMPtr<nsPrintEngine> mPrintEngine; + nsRefPtr<nsPrintEngine> mPrintEngine; float mOriginalPrintPreviewScale; float mPrintPreviewZoom; nsAutoPtr<nsPrintEventDispatcher> mBeforeAndAfterPrint; #endif // NS_PRINT_PREVIEW #ifdef DEBUG FILE* mDebugFile; #endif // DEBUG
--- a/layout/printing/Makefile.in +++ b/layout/printing/Makefile.in @@ -32,11 +32,12 @@ CPPSRCS = \ FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir)/../base \ -I$(srcdir)/../../content/base/src \ + -I$(srcdir)/../../view/src \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT
--- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -13,16 +13,19 @@ #include "nsIScriptGlobalObject.h" #include "nsPIDOMWindow.h" #include "nsIDocShell.h" #include "nsIFrame.h" #include "nsIURI.h" #include "nsITextToSubURI.h" #include "nsError.h" +#include "nsView.h" +#include "nsAsyncDOMEvent.h" + // Print Options #include "nsIPrintSettings.h" #include "nsIPrintSettingsService.h" #include "nsIPrintOptions.h" #include "nsIPrintSession.h" #include "nsGfxCIID.h" #include "nsIServiceManager.h" #include "nsGkAtoms.h" @@ -204,33 +207,36 @@ public: protected: nsRefPtr<nsPrintEngine> mPrintEngine; bool mSuppressed; }; // Class IDs static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); -NS_IMPL_ISUPPORTS1(nsPrintEngine, nsIObserver) +NS_IMPL_ISUPPORTS3(nsPrintEngine, nsIWebProgressListener, + nsISupportsWeakReference, nsIObserver) //--------------------------------------------------- //-- nsPrintEngine Class Impl //--------------------------------------------------- nsPrintEngine::nsPrintEngine() : mIsCreatingPrintPreview(false), mIsDoingPrinting(false), mIsDoingPrintPreview(false), mProgressDialogIsShown(false), mScreenDPI(115.0f), mPrt(nullptr), mPagePrintTimer(nullptr), mPageSeqFrame(nullptr), mPrtPreview(nullptr), mOldPrtPreview(nullptr), - mDebugFile(nullptr) + mDebugFile(nullptr), + mLoadCounter(0), + mDidLoadDataForPrinting(false) { } //------------------------------------------------------- nsPrintEngine::~nsPrintEngine() { Destroy(); // for insurance } @@ -667,37 +673,54 @@ nsPrintEngine::DoCommonPrint(bool mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); } } } else { mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); } } + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + CheckForChildFrameSets(mPrt->mPrintObject); + } + + if (NS_FAILED(EnablePOsForPrinting())) { + return NS_ERROR_FAILURE; + } + + // Attach progressListener to catch network requests. + nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell); + webProgress->AddProgressListener( + static_cast<nsIWebProgressListener*>(this), + nsIWebProgress::NOTIFY_STATE_REQUEST); + + mLoadCounter = 0; + mDidLoadDataForPrinting = false; + if (aIsPrintPreview) { bool notifyOnInit = false; ShowPrintProgress(false, notifyOnInit); // Very important! Turn Off scripting TurnScriptingOn(false); if (!notifyOnInit) { - rv = FinishPrintPreview(); + InstallPrintPreviewListener(); + rv = InitPrintDocConstruction(false); } else { rv = NS_OK; } - NS_ENSURE_SUCCESS(rv, rv); } else { bool doNotify; ShowPrintProgress(true, doNotify); if (!doNotify) { // Print listener setup... mPrt->OnStartPrinting(); - rv = DocumentReadyForPrinting(); - NS_ENSURE_SUCCESS(rv, rv); + + rv = InitPrintDocConstruction(false); } } // We will enable scripting later after printing has finished. scriptSuppressor.Disconnect(); return NS_OK; } @@ -799,20 +822,29 @@ nsPrintEngine::GetIsFramesetFrameSelecte //---------------------------------------------------------------------------------- /* readonly attribute long printPreviewNumPages; */ NS_IMETHODIMP nsPrintEngine::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages) { NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); + nsPrintData* prt = nullptr; nsIFrame* seqFrame = nullptr; *aPrintPreviewNumPages = 0; - if (!mPrtPreview || - NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { + + // When calling this function, the FinishPrintPreview() function might not + // been called as there are still some + if (mPrtPreview) { + prt = mPrtPreview; + } else { + prt = mPrt; + } + if ((!prt) || + NS_FAILED(GetSeqFrameAndCountPagesInternal(prt->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { return NS_ERROR_FAILURE; } return NS_OK; } //---------------------------------------------------------------------------------- // Enumerate all the documents for their titles NS_IMETHODIMP @@ -1593,111 +1625,136 @@ nsPrintEngine::ShowPrintErrorDialog(nsre dialog->Alert(title.get(), msg.get()); PR_PL(("ShowPrintErrorDialog(): alert displayed successfully.\n")); } //----------------------------------------------------------------- //-- Section: Reflow Methods //----------------------------------------------------------------- +nsresult +nsPrintEngine::ReconstructAndReflow(bool doSetPixelScale) +{ +#if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING) + // We need to clear all the output files here + // because they will be re-created with second reflow of the docs + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; + } +#endif + + for (uint32_t i = 0; i < mPrt->mPrintDocList.Length(); ++i) { + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + + if (po->mDontPrint || po->mInvisible) { + continue; + } + + UpdateZoomRatio(po, doSetPixelScale); + + po->mPresContext->SetPageScale(po->mZoomRatio); + + // Calculate scale factor from printer to screen + float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) / + float(mPrt->mPrintDC->AppUnitsPerDevPixel()); + po->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI); + + po->mPresShell->ReconstructFrames(); + + // For all views except the first one, setup the root view. + // ??? Can there be multiple po for the top-level-document? + bool documentIsTopLevel = true; + if (i != 0) { + nsSize adjSize; + bool doReturn; + nsresult rv = SetRootView(po, doReturn, documentIsTopLevel, adjSize); + + MOZ_ASSERT(!documentIsTopLevel, "How could this happen?"); + + if (NS_FAILED(rv) || doReturn) { + return rv; + } + } + + po->mPresShell->FlushPendingNotifications(Flush_Layout); + + nsresult rv = UpdateSelectionAndShrinkPrintObject(po, documentIsTopLevel); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + //------------------------------------------------------- nsresult nsPrintEngine::SetupToPrintContent() { - // In this step we figure out which documents should be printed - // i.e. if we are printing the selection then only enable that nsPrintObject - // for printing - if (NS_FAILED(EnablePOsForPrinting())) { - return NS_ERROR_FAILURE; + nsresult rv; + + bool didReconstruction = false; + + // If some new content got loaded since the initial reflow rebuild + // everything. + if (mDidLoadDataForPrinting) { + rv = ReconstructAndReflow(DoSetPixelScale()); + didReconstruction = true; + NS_ENSURE_SUCCESS(rv, rv); } - DUMP_DOC_LIST("\nAfter Enable------------------------------------------"); - - // This is an Optimization - // If we are in PP then we already know all the shrinkage information - // so just transfer it to the PrintData and we will skip the extra shrinkage reflow - // - // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC - // The first time we do not want to do this, the second time through we do - bool doSetPixelScale = false; + + // Here is where we figure out if extra reflow for shrinking the content + // is required. + // But skip this step if we are in PrintPreview bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; - if (ppIsShrinkToFit) { - mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; - doSetPixelScale = true; - } - - // Here we reflow all the PrintObjects - nsresult rv = ReflowDocList(mPrt->mPrintObject, doSetPixelScale); - if (NS_FAILED(rv)) { - return NS_ERROR_FAILURE; - } - - // Here is where we do the extra reflow for shrinking the content - // But skip this step if we are in PrintPreview if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { // Now look for the PO that has the smallest percent for shrink to fit if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { nsPrintObject* smallestPO = FindSmallestSTF(); NS_ASSERTION(smallestPO, "There must always be an XMost PO!"); if (smallestPO) { // Calc the shrinkage based on the entire content area mPrt->mShrinkRatio = smallestPO->mShrinkRatio; } } else { // Single document so use the Shrink as calculated for the PO mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; } - // Only Shrink if we are smaller if (mPrt->mShrinkRatio < 0.998f) { - for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) { - nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); - NS_ASSERTION(po, "nsPrintObject can't be null!"); - // Wipe out the presentation before we reflow - po->DestroyPresentation(); - } - -#if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING) - // We need to clear all the output files here - // because they will be re-created with second reflow of the docs - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - gDumpFileNameCnt = 0; - gDumpLOFileNameCnt = 0; - } -#endif - - // Here we reflow all the PrintObjects a second time - // this time using the shrinkage values - // The last param here tells reflow to NOT calc the shrinkage values - if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, true))) { - return NS_ERROR_FAILURE; - } + rv = ReconstructAndReflow(true); + didReconstruction = true; + NS_ENSURE_SUCCESS(rv, rv); } #ifdef PR_LOGGING - { - float calcRatio = 0.0f; - if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { - nsPrintObject* smallestPO = FindSmallestSTF(); - NS_ASSERTION(smallestPO, "There must always be an XMost PO!"); - if (smallestPO) { - // Calc the shrinkage based on the entire content area - calcRatio = smallestPO->mShrinkRatio; - } - } else { - // Single document so use the Shrink as calculated for the PO - calcRatio = mPrt->mPrintObject->mShrinkRatio; + float calcRatio = 0.0f; + if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { + nsPrintObject* smallestPO = FindSmallestSTF(); + NS_ASSERTION(smallestPO, "There must always be an XMost PO!"); + if (smallestPO) { + // Calc the shrinkage based on the entire content area + calcRatio = smallestPO->mShrinkRatio; } - PR_PL(("**************************************************************************\n")); - PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); - PR_PL(("**************************************************************************\n")); + } else { + // Single document so use the Shrink as calculated for the PO + calcRatio = mPrt->mPrintObject->mShrinkRatio; } + PR_PL(("**************************************************************************\n")); + PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); + PR_PL(("**************************************************************************\n")); #endif } - + + // If the frames got reconstructed and reflowed the number of pages might + // has changed. + if (didReconstruction) { + FirePrintPreviewUpdateEvent(); + } + DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); PR_PL(("\n")); PR_PL(("-------------------------------------------------------\n")); PR_PL(("\n")); CalcNumPrintablePages(mPrt->mNumPrintablePages); PR_PL(("--- Printing %d pages\n", mPrt->mNumPrintablePages)); @@ -1787,67 +1844,273 @@ nsPrintEngine::ReflowDocList(nsPrintObje nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr; if (!frame || !frame->GetStyleVisibility()->IsVisible()) { aPO->mDontPrint = true; aPO->mInvisible = true; return NS_OK; } } + UpdateZoomRatio(aPO, aSetPixelScale); + + nsresult rv; + // Reflow the PO + rv = ReflowPrintObject(aPO); + NS_ENSURE_SUCCESS(rv, rv); + + int32_t cnt = aPO->mKids.Length(); + for (int32_t i=0;i<cnt;i++) { + rv = ReflowDocList(aPO->mKids[i], aSetPixelScale); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +void +nsPrintEngine::FirePrintPreviewUpdateEvent() +{ + // Dispatch the event only while in PrintPreview. When printing, there is no + // listener bound to this event and therefore no need to dispatch it. + if (mIsDoingPrintPreview && !mIsDoingPrinting) { + nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint); + (new nsAsyncDOMEvent( + cv->GetDocument(), NS_LITERAL_STRING("printPreviewUpdate"), true, true) + )->RunDOMEventWhenSafe(); + } +} + +nsresult +nsPrintEngine::InitPrintDocConstruction(bool aHandleError) +{ + nsresult rv; + rv = ReflowDocList(mPrt->mPrintObject, DoSetPixelScale()); + NS_ENSURE_SUCCESS(rv, rv); + + FirePrintPreviewUpdateEvent(); + + if (mLoadCounter == 0) { + AfterNetworkPrint(aHandleError); + } + return rv; +} + +nsresult +nsPrintEngine::AfterNetworkPrint(bool aHandleError) +{ + nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell); + + webProgress->RemoveProgressListener( + static_cast<nsIWebProgressListener*>(this)); + + nsresult rv; + if (mIsDoingPrinting) { + rv = DocumentReadyForPrinting(); + } else { + rv = FinishPrintPreview(); + } + + /* cleaup on failure + notify user */ + if (aHandleError && NS_FAILED(rv)) { + CleanupOnFailure(rv, !mIsDoingPrinting); + } + + return rv; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsIWebProgressListener + +NS_IMETHODIMP +nsPrintEngine::OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aStateFlags, + nsresult aStatus) +{ + nsAutoCString name; + aRequest->GetName(name); + if (name.Equals("about:document-onload-blocker")) { + return NS_OK; + } + if (aStateFlags & STATE_START) { + nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); + + ++mLoadCounter; + } else if (aStateFlags & STATE_STOP) { + mDidLoadDataForPrinting = true; + --mLoadCounter; + + // If all resources are loaded, then do a small timeout and if there + // are still no new requests, then another reflow. + if (mLoadCounter == 0) { + AfterNetworkPrint(true); + } + } + return NS_OK; +} + + + +NS_IMETHODIMP +nsPrintEngine::OnProgressChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI* aLocation, + uint32_t aFlags) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintEngine::OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + nsresult aStatus, + const PRUnichar *aMessage) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + uint32_t aState) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +//------------------------------------------------------- + +void +nsPrintEngine::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale) +{ // Here is where we set the shrinkage value into the DC // and this is what actually makes it shrink if (aSetPixelScale && aPO->mFrameType != eIFrame) { float ratio; if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { ratio = mPrt->mShrinkRatio - 0.005f; // round down } else { ratio = aPO->mShrinkRatio - 0.005f; // round down } aPO->mZoomRatio = ratio; } else if (!mPrt->mShrinkToFit) { double scaling; mPrt->mPrintSettings->GetScaling(&scaling); aPO->mZoomRatio = float(scaling); + } +} + +nsresult +nsPrintEngine::UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO, + bool aDocumentIsTopLevel) +{ + nsCOMPtr<nsIPresShell> displayShell; + aPO->mDocShell->GetPresShell(getter_AddRefs(displayShell)); + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr<nsISelection> selection, selectionPS; + // It's okay if there is no display shell, just skip copying the selection + if (displayShell) { + selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); } - - nsresult rv; - // Reflow the PO - rv = ReflowPrintObject(aPO); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t cnt = aPO->mKids.Length(); - for (int32_t i=0;i<cnt;i++) { - rv = ReflowDocList(aPO->mKids[i], aSetPixelScale); - NS_ENSURE_SUCCESS(rv, rv); + selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); + + // Reset all existing selection ranges that might have been added by calling + // this function before. + if (selectionPS) { + selectionPS->RemoveAllRanges(); + } + if (selection && selectionPS) { + int32_t cnt; + selection->GetRangeCount(&cnt); + int32_t inx; + for (inx = 0; inx < cnt; ++inx) { + nsCOMPtr<nsIDOMRange> range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) + selectionPS->AddRange(range); + } + } + + // If we are trying to shrink the contents to fit on the page + // we must first locate the "pageContent" frame + // Then we walk the frame tree and look for the "xmost" frame + // this is the frame where the right-hand side of the frame extends + // the furthest + if (mPrt->mShrinkToFit && aDocumentIsTopLevel) { + nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame(); + NS_ENSURE_STATE(pageSequence); + pageSequence->GetSTFPercent(aPO->mShrinkRatio); } return NS_OK; } -//------------------------------------------------------- -// Reflow a nsPrintObject -nsresult -nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO) +bool +nsPrintEngine::DoSetPixelScale() +{ + // This is an Optimization + // If we are in PP then we already know all the shrinkage information + // so just transfer it to the PrintData and we will skip the extra shrinkage reflow + // + // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC + // The first time we do not want to do this, the second time through we do + bool doSetPixelScale = false; + bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; + if (ppIsShrinkToFit) { + mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; + doSetPixelScale = true; + } + return doSetPixelScale; +} + +nsIView* +nsPrintEngine::GetParentViewForRoot() { - NS_ASSERTION(aPO, "Pointer is null!"); - if (!aPO) return NS_ERROR_FAILURE; - - nsSize adjSize; - bool documentIsTopLevel; - if (!aPO->IsPrintable()) - return NS_OK; - + if (mIsCreatingPrintPreview) { + nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint); + if (cv) { + return cv->FindContainerView(); + } + } + return nullptr; +} + +nsresult +nsPrintEngine::SetRootView( + nsPrintObject* aPO, + bool& doReturn, + bool& documentIsTopLevel, + nsSize& adjSize +) +{ bool canCreateScrollbars = true; + + nsIView* rootView; nsIView* parentView = nullptr; + doReturn = false; + if (aPO->mParent && aPO->mParent->IsPrintable()) { nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr; // Without a frame, this document can't be displayed; therefore, there is no // point to reflowing it if (!frame) { SetPrintPO(aPO, false); + doReturn = true; return NS_OK; } //XXX If printing supported printing document hierarchies with non-constant // zoom this would be wrong as we use the same mPrt->mPrintDC for all // subdocuments. adjSize = frame->GetContentRect().Size(); documentIsTopLevel = false; @@ -1862,31 +2125,61 @@ nsPrintEngine::ReflowPrintObject(nsPrint parentView = view; canCreateScrollbars = false; } } else { nscoord pageWidth, pageHeight; mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); adjSize = nsSize(pageWidth, pageHeight); documentIsTopLevel = true; - - if (mIsCreatingPrintPreview) { - nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint); - if (cv) { - parentView = cv->FindContainerView(); - } - } + parentView = GetParentViewForRoot(); + } + + if (aPO->mPresShell->GetViewManager()->GetRootView()) { + // Reuse the root view that is already on the root frame. + rootView = aPO->mPresShell->GetRootFrame()->GetView(); + reinterpret_cast<nsView*>(rootView)->SetParent(reinterpret_cast<nsView*>(parentView)); + } else { + // Create a child window of the parent that is our "root view/window" + nsRect tbounds = nsRect(nsPoint(0, 0), adjSize); + rootView = aPO->mViewManager->CreateView(tbounds, parentView); + NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY); + } + + if (mIsCreatingPrintPreview && documentIsTopLevel) { + aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); } + // Setup hierarchical relationship in view manager + aPO->mViewManager->SetRootView(rootView); + + return NS_OK; +} + +// Reflow a nsPrintObject +nsresult +nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO) +{ + NS_ENSURE_STATE(aPO); + + if (!aPO->IsPrintable()) { + return NS_OK; + } + NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext"); // create the PresContext - aPO->mPresContext = new nsPresContext(aPO->mDocument, - mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview: - nsPresContext::eContext_Print); + nsPresContext::nsPresContextType type = + mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview: + nsPresContext::eContext_Print; + nsIView* parentView = + aPO->mParent && aPO->mParent->IsPrintable() ? nullptr : GetParentViewForRoot(); + aPO->mPresContext = parentView ? + new nsPresContext(aPO->mDocument, type) : + new nsRootPresContext(aPO->mDocument, type); NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY); aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings); // set the presentation context to the value in the print settings bool printBGColors; mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); aPO->mPresContext->SetBackgroundColorDraw(printBGColors); mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); @@ -1912,30 +2205,30 @@ nsPrintEngine::ReflowPrintObject(nsPrint delete styleSet; return rv; } styleSet->EndUpdate(); // The pres shell now owns the style set object. - PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO, + + bool doReturn = false;; + bool documentIsTopLevel = false; + nsSize adjSize; + + rv = SetRootView(aPO, doReturn, documentIsTopLevel, adjSize); + + if (NS_FAILED(rv) || doReturn) { + return rv; + } + + PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n", aPO, aPO->mPresShell.get(), gFrameTypesStr[aPO->mFrameType], adjSize.width, adjSize.height)); - // Create a child window of the parent that is our "root view/window" - nsRect tbounds = nsRect(nsPoint(0, 0), adjSize); - nsIView* rootView = aPO->mViewManager->CreateView(tbounds, parentView); - NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY); - - if (mIsCreatingPrintPreview && documentIsTopLevel) { - aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); - } - - // Setup hierarchical relationship in view manager - aPO->mViewManager->SetRootView(rootView); // This docshell stuff is weird; will go away when we stop having multiple // presentations per document nsCOMPtr<nsISupports> supps(do_QueryInterface(aPO->mDocShell)); aPO->mPresContext->SetContainer(supps); aPO->mPresShell->BeginObservingDocument(); @@ -1956,46 +2249,18 @@ nsPrintEngine::ReflowPrintObject(nsPrint rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(aPO->mPresShell, "Presshell should still be here"); // Process the reflow event Initialize posted aPO->mPresShell->FlushPendingNotifications(Flush_Layout); - nsCOMPtr<nsIPresShell> displayShell; - aPO->mDocShell->GetPresShell(getter_AddRefs(displayShell)); - // Transfer Selection Ranges to the new Print PresShell - nsCOMPtr<nsISelection> selection, selectionPS; - // It's okay if there is no display shell, just skip copying the selection - if (displayShell) { - selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); - } - selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); - if (selection && selectionPS) { - int32_t cnt; - selection->GetRangeCount(&cnt); - int32_t inx; - for (inx=0;inx<cnt;inx++) { - nsCOMPtr<nsIDOMRange> range; - if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) - selectionPS->AddRange(range); - } - } - - // If we are trying to shrink the contents to fit on the page - // we must first locate the "pageContent" frame - // Then we walk the frame tree and look for the "xmost" frame - // this is the frame where the right-hand side of the frame extends - // the furthest - if (mPrt->mShrinkToFit && documentIsTopLevel) { - nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame(); - NS_ENSURE_STATE(pageSequence); - pageSequence->GetSTFPercent(aPO->mShrinkRatio); - } + rv = UpdateSelectionAndShrinkPrintObject(aPO, documentIsTopLevel); + NS_ENSURE_SUCCESS(rv, rv); #ifdef EXTENDED_DEBUG_PRINTING if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { char * docStr; char * urlStr; GetDocTitleAndURL(aPO, docStr, urlStr); char filename[256]; sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); @@ -3304,17 +3569,16 @@ nsPrintEngine::FinishPrintPreview() // before it is to be created if (mIsDoingPrintPreview && mOldPrtPreview) { delete mOldPrtPreview; mOldPrtPreview = nullptr; } - InstallPrintPreviewListener(); mPrt->OnEndPrinting(); // PrintPreview was built using the mPrt (code reuse) // then we assign it over mPrtPreview = mPrt; mPrt = nullptr; @@ -3347,32 +3611,19 @@ nsPrintEngine::StartPagePrintTimer(nsPri } /*=============== nsIObserver Interface ======================*/ NS_IMETHODIMP nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { nsresult rv = NS_ERROR_FAILURE; - if (mIsDoingPrinting) { - rv = DocumentReadyForPrinting(); - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - CleanupOnFailure(rv, true); - } - } else { - rv = FinishPrintPreview(); - if (NS_FAILED(rv)) { - CleanupOnFailure(rv, false); - } - if (mPrtPreview) { + rv = InitPrintDocConstruction(true); + if (!mIsDoingPrinting && mPrtPreview) { mPrtPreview->OnEndPrinting(); - } - rv = NS_OK; } return rv; } //--------------------------------------------------------------- //-- PLEvent Notification
--- a/layout/printing/nsPrintEngine.h +++ b/layout/printing/nsPrintEngine.h @@ -8,17 +8,20 @@ #include "mozilla/Attributes.h" #include "nsCOMPtr.h" #include "nsPrintObject.h" #include "nsPrintData.h" #include "nsFrameList.h" #include "mozilla/Attributes.h" +#include "nsIWebProgress.h" #include "nsHTMLCanvasElement.h" +#include "nsIWebProgressListener.h" +#include "nsWeakReference.h" // Interfaces #include "nsIDocument.h" #include "nsIDOMWindow.h" #include "nsIObserver.h" // Classes class nsPagePrintTimer; @@ -29,25 +32,29 @@ class nsPrintObject; class nsIDocShell; class nsIPageSequenceFrame; class nsIWeakReference; //------------------------------------------------------------------------ // nsPrintEngine Class // //------------------------------------------------------------------------ -class nsPrintEngine MOZ_FINAL : public nsIObserver +class nsPrintEngine MOZ_FINAL : public nsIObserver, + public nsIWebProgressListener, + public nsSupportsWeakReference { public: // nsISupports interface... NS_DECL_ISUPPORTS // nsIObserver NS_DECL_NSIOBSERVER + NS_DECL_NSIWEBPROGRESSLISTENER + // Old nsIWebBrowserPrint methods; not cleaned up yet NS_IMETHOD Print(nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aWebProgressListener); NS_IMETHOD PrintPreview(nsIPrintSettings* aPrintSettings, nsIDOMWindow *aChildDOMWin, nsIWebProgressListener* aWebProgressListener); NS_IMETHOD GetIsFramesetDocument(bool *aIsFramesetDocument); NS_IMETHOD GetIsIFrameSelected(bool *aIsIFrameSelected); @@ -266,13 +273,30 @@ protected: // Print Preview nsPrintData* mPrtPreview; nsPrintData* mOldPrtPreview; nsCOMPtr<nsIDocument> mDocument; FILE* mDebugFile; + int32_t mLoadCounter; + bool mDidLoadDataForPrinting; + + nsresult AfterNetworkPrint(bool aHandleError); + + nsresult SetRootView(nsPrintObject* aPO, + bool& aDoReturn, + bool& aDocumentIsTopLevel, + nsSize& aAdjSize); + nsIView* GetParentViewForRoot(); + bool DoSetPixelScale(); + void UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale); + nsresult ReconstructAndReflow(bool aDoSetPixelScale); + nsresult UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO, + bool aDocumentIsTopLevel); + nsresult InitPrintDocConstruction(bool aHandleError); + void FirePrintPreviewUpdateEvent(); private: nsPrintEngine& operator=(const nsPrintEngine& aOther) MOZ_DELETE; }; #endif /* nsPrintEngine_h___ */