This commit is contained in:
Olli Pettay 2009-03-08 21:01:02 +02:00
Родитель 7aac9e4432
Коммит c10a9dfb86
15 изменённых файлов: 336 добавлений и 47 удалений

Просмотреть файл

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

Просмотреть файл

@ -106,6 +106,7 @@ nsTextFragment::Shutdown()
nsTextFragment::~nsTextFragment() nsTextFragment::~nsTextFragment()
{ {
ReleaseText(); ReleaseText();
MOZ_COUNT_DTOR(nsTextFragment);
} }
void void

Просмотреть файл

@ -45,6 +45,7 @@
#define nsTextFragment_h___ #define nsTextFragment_h___
#include "nsAString.h" #include "nsAString.h"
#include "nsTraceRefcnt.h"
class nsString; class nsString;
class nsCString; class nsCString;
@ -88,6 +89,7 @@ public:
nsTextFragment() nsTextFragment()
: m1b(nsnull), mAllBits(0) : m1b(nsnull), mAllBits(0)
{ {
MOZ_COUNT_CTOR(nsTextFragment);
NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!"); NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
} }

Просмотреть файл

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

Просмотреть файл

@ -456,6 +456,8 @@ protected:
unsigned mClosingWhilePrinting : 1; unsigned mClosingWhilePrinting : 1;
#if NS_PRINT_PREVIEW #if NS_PRINT_PREVIEW
unsigned mPrintPreviewZoomed : 1;
// These data members support delayed printing when the document is loading // These data members support delayed printing when the document is loading
unsigned mPrintIsPending : 1; unsigned mPrintIsPending : 1;
unsigned mPrintDocIsFullyLoaded : 1; unsigned mPrintDocIsFullyLoaded : 1;
@ -463,6 +465,8 @@ protected:
nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner; nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
nsCOMPtr<nsPrintEngine> mPrintEngine; nsCOMPtr<nsPrintEngine> mPrintEngine;
float mOriginalPrintPreviewScale;
float mPrintPreviewZoom;
#endif // NS_PRINT_PREVIEW #endif // NS_PRINT_PREVIEW
#ifdef NS_DEBUG #ifdef NS_DEBUG
@ -536,6 +540,9 @@ void DocumentViewerImpl::PrepareToStartLoad()
DocumentViewerImpl::DocumentViewerImpl() DocumentViewerImpl::DocumentViewerImpl()
: mTextZoom(1.0), mPageZoom(1.0), : mTextZoom(1.0), mPageZoom(1.0),
mIsSticky(PR_TRUE), mIsSticky(PR_TRUE),
#ifdef NS_PRINT_PREVIEW
mPrintPreviewZoom(1.0),
#endif
mHintCharsetSource(kCharsetUninitialized) mHintCharsetSource(kCharsetUninitialized)
{ {
PrepareToStartLoad(); PrepareToStartLoad();
@ -2722,10 +2729,12 @@ SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure)
NS_IMETHODIMP NS_IMETHODIMP
DocumentViewerImpl::SetTextZoom(float aTextZoom) DocumentViewerImpl::SetTextZoom(float aTextZoom)
{ {
if (!GetIsPrintPreview()) { if (GetIsPrintPreview()) {
mTextZoom = aTextZoom; return NS_OK;
} }
mTextZoom = aTextZoom;
nsIViewManager::UpdateViewBatch batch(GetViewManager()); nsIViewManager::UpdateViewBatch batch(GetViewManager());
// Set the text zoom on all children of mContainer (even if our zoom didn't // Set the text zoom on all children of mContainer (even if our zoom didn't
@ -2761,9 +2770,39 @@ DocumentViewerImpl::GetTextZoom(float* aTextZoom)
NS_IMETHODIMP NS_IMETHODIMP
DocumentViewerImpl::SetFullZoom(float aFullZoom) DocumentViewerImpl::SetFullZoom(float aFullZoom)
{ {
if (!GetIsPrintPreview()) { #ifdef NS_PRINT_PREVIEW
mPageZoom = aFullZoom; if (GetIsPrintPreview()) {
nsPresContext* pc = GetPresContext();
NS_ENSURE_TRUE(pc, NS_OK);
nsCOMPtr<nsIPresShell> shell = pc->GetPresShell();
NS_ENSURE_TRUE(shell, NS_OK);
nsIViewManager::UpdateViewBatch batch(pc->GetViewManager());
if (!mPrintPreviewZoomed) {
mOriginalPrintPreviewScale = pc->GetPrintPreviewScale();
mPrintPreviewZoomed = PR_TRUE;
}
mPrintPreviewZoom = aFullZoom;
pc->SetPrintPreviewScale(aFullZoom * mOriginalPrintPreviewScale);
nsIPageSequenceFrame* pf = nsnull;
shell->GetPageSequenceFrame(&pf);
if (pf) {
nsIFrame* f = do_QueryFrame(pf);
shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
}
nsIFrame* rootFrame = shell->GetRootFrame();
if (rootFrame) {
nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
rootFrame->Invalidate(rect);
}
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return NS_OK;
} }
#endif
mPageZoom = aFullZoom;
nsIViewManager::UpdateViewBatch batch(GetViewManager()); nsIViewManager::UpdateViewBatch batch(GetViewManager());
@ -2787,6 +2826,12 @@ NS_IMETHODIMP
DocumentViewerImpl::GetFullZoom(float* aFullZoom) DocumentViewerImpl::GetFullZoom(float* aFullZoom)
{ {
NS_ENSURE_ARG_POINTER(aFullZoom); NS_ENSURE_ARG_POINTER(aFullZoom);
#ifdef NS_PRINT_PREVIEW
if (GetIsPrintPreview()) {
*aFullZoom = mPrintPreviewZoom;
return NS_OK;
}
#endif
// Check the prescontext first because it might have a temporary // Check the prescontext first because it might have a temporary
// setting for print-preview // setting for print-preview
nsPresContext* pc = GetPresContext(); nsPresContext* pc = GetPresContext();
@ -3622,6 +3667,7 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings,
} }
rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener); rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener);
mPrintPreviewZoomed = PR_FALSE;
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
OnDonePrinting(); OnDonePrinting();
} }

Просмотреть файл

@ -80,6 +80,7 @@
#include "gfxTypes.h" #include "gfxTypes.h"
#include "gfxUserFontSet.h" #include "gfxUserFontSet.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsTextFragment.h"
#ifdef MOZ_SVG #ifdef MOZ_SVG
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
@ -3175,6 +3176,45 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame)
parentType == nsGkAtoms::pageContentFrame; parentType == nsGkAtoms::pageContentFrame;
} }
static void DeleteTextFragment(void* aObject, nsIAtom* aPropertyName,
void* aPropertyValue, void* aData)
{
delete static_cast<nsTextFragment*>(aPropertyValue);
}
/* static */ nsresult
nsLayoutUtils::InitTextRunContainerForPrinting(nsIContent* aContent,
nsIFrame* aFrame,
nsFrameState aBits)
{
NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame ||
aFrame->GetType() == nsGkAtoms::svgGlyphFrame,
"Wrong frame type!");
nsPresContext* presContext = aFrame->PresContext();
if (presContext->IsDynamic()) {
return NS_OK;
}
if (!presContext->PropertyTable()->
GetProperty(aContent, nsGkAtoms::clonedTextForPrint)) {
nsTextFragment* frag = new nsTextFragment();
NS_ENSURE_TRUE(frag, NS_ERROR_OUT_OF_MEMORY);
*frag = *aContent->GetText();
nsresult rv = presContext->PropertyTable()->
SetProperty(aContent, nsGkAtoms::clonedTextForPrint, frag,
DeleteTextFragment, nsnull);
if (NS_FAILED(rv)) {
delete frag;
return rv;
}
}
aFrame->AddStateBits(aBits);
return NS_OK;
}
nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
const nsAString& aValue) const nsAString& aValue)
: mContent(aContent), : mContent(aContent),

Просмотреть файл

@ -958,6 +958,21 @@ public:
* disabled. * disabled.
*/ */
static PRBool sDisableGetUsedXAssertions; static PRBool sDisableGetUsedXAssertions;
/**
* Initilizes text run container for printing. Does *nothing* if
* aFrame->PresContext() is dynamic.
* @param aContainerContent The nsIContent object from which aFrame gets data
* for text run creation.
* @param aFrame The nsIFrame object which is being initialized.
* @param aBits Frame type dependent bits which will be set to
* aFrame to mark that PresContext has a text fragment
* property called nsGkAtoms::clonedTextForPrint for
* aContent.
*/
static nsresult InitTextRunContainerForPrinting(nsIContent* aContainerContent,
nsIFrame* aFrame,
nsFrameState aBits);
}; };
class nsAutoDisableGetUsedXAssertions class nsAutoDisableGetUsedXAssertions

Просмотреть файл

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

Просмотреть файл

@ -766,6 +766,119 @@ struct nsCallbackEventRequest
nsCallbackEventRequest* next; nsCallbackEventRequest* next;
}; };
class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
{
public:
nsDocumentObserverForNonDynamicPresContext(nsIDocumentObserver* 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 || IsInRootScrollbar(aContent1)) &&
(!aContent2 || IsInRootScrollbar(aContent2))) {
mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
aStateMask);
}
}
// nsIMutationObserver
virtual void CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
if (IsInRootScrollbar(aContent)) {
mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
}
}
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
PRUint32 aStateMask)
{
if (IsInRootScrollbar(aContent)) {
mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
aAttribute, aModType, aStateMask);
}
}
virtual void ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
if (IsInRootScrollbar(aContainer)) {
mBaseObserver->ContentAppended(aDocument, aContainer,
aNewIndexInContainer);
}
}
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (IsInRootScrollbar(aContainer)) {
mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
aIndexInContainer);
}
}
virtual void ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (IsInRootScrollbar(aContainer)) {
mBaseObserver->ContentRemoved(aDocument, aContainer, aChild,
aIndexInContainer);
}
}
PRBool IsInRootScrollbar(nsIContent* aContent) {
if(aContent && aContent->IsInDoc()) {
nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
while (aContent && aContent->IsInNativeAnonymousSubtree()) {
nsIContent* parent = aContent->GetParent();
if (parent == root && aContent->IsNodeOfType(nsINode::eXUL)) {
nsIAtom* tag = aContent->Tag();
return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
}
aContent = parent;
}
}
return PR_FALSE;
}
protected:
nsCOMPtr<nsIDocumentObserver> mBaseObserver;
};
NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
nsIDocumentObserver,
nsIMutationObserver)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class nsPresShellEventCB; class nsPresShellEventCB;
@ -1198,6 +1311,9 @@ protected:
static PRBool sDisableNonTestMouseEvents; static PRBool sDisableNonTestMouseEvents;
nsCOMPtr<nsIDocumentObserver> mDocumentObserverForNonDynamicContext;
private: private:
PRBool InZombieDocument(nsIContent *aContent); PRBool InZombieDocument(nsIContent *aContent);
@ -2268,7 +2384,14 @@ NS_IMETHODIMP
PresShell::BeginObservingDocument() PresShell::BeginObservingDocument()
{ {
if (mDocument && !mIsDestroying) { if (mDocument && !mIsDestroying) {
mDocument->AddObserver(this); if (mPresContext->IsDynamic()) {
mDocument->AddObserver(this);
} else {
mDocumentObserverForNonDynamicContext =
new nsDocumentObserverForNonDynamicPresContext(this);
NS_ENSURE_TRUE(mDocumentObserverForNonDynamicContext, NS_ERROR_OUT_OF_MEMORY);
mDocument->AddObserver(mDocumentObserverForNonDynamicContext);
}
if (mIsDocumentGone) { if (mIsDocumentGone) {
NS_WARNING("Adding a presshell that was disconnected from the document " NS_WARNING("Adding a presshell that was disconnected from the document "
"as a document observer? Sounds wrong..."); "as a document observer? Sounds wrong...");
@ -2286,7 +2409,10 @@ PresShell::EndObservingDocument()
// is gone, perhaps? Except for printing it's NOT gone, sometimes. // is gone, perhaps? Except for printing it's NOT gone, sometimes.
mIsDocumentGone = PR_TRUE; mIsDocumentGone = PR_TRUE;
if (mDocument) { if (mDocument) {
mDocument->RemoveObserver(this); mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ?
mDocumentObserverForNonDynamicContext.get() :
this);
mDocumentObserverForNonDynamicContext = nsnull;
} }
return NS_OK; return NS_OK;
} }
@ -3357,6 +3483,10 @@ PresShell::RecreateFramesFor(nsIContent* aContent)
return NS_OK; return NS_OK;
} }
if (!mPresContext->IsDynamic()) {
return NS_OK;
}
// Don't call RecreateFramesForContent since that is not exported and we want // Don't call RecreateFramesForContent since that is not exported and we want
// to keep the number of entrypoints down. // to keep the number of entrypoints down.
@ -4770,6 +4900,9 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
nsresult nsresult
PresShell::ReconstructFrames(void) PresShell::ReconstructFrames(void)
{ {
if (!mPresContext || !mPresContext->IsDynamic()) {
return NS_OK;
}
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
mFrameConstructor->BeginUpdate(); mFrameConstructor->BeginUpdate();
nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy(); nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();

Просмотреть файл

@ -172,8 +172,8 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
// it right in paginated mode. // it right in paginated mode.
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
// Return our desired size // Return our desired size
aDesiredSize.height = mSize.height; aDesiredSize.height = mSize.height * PresContext()->GetPrintPreviewScale();
aDesiredSize.width = mSize.width; aDesiredSize.width = mSize.width * PresContext()->GetPrintPreviewScale();
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width,
aDesiredSize.height); aDesiredSize.height);
FinishAndStoreOverflow(&aDesiredSize); FinishAndStoreOverflow(&aDesiredSize);
@ -355,8 +355,9 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
// Return our desired size // Return our desired size
// Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the // Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the
// correct size // correct size
nscoord w = (x + availSize.width + deadSpaceGap);
aDesiredSize.height = y * PresContext()->GetPrintPreviewScale(); // includes page heights and dead space aDesiredSize.height = y * PresContext()->GetPrintPreviewScale(); // includes page heights and dead space
aDesiredSize.width = (x + availSize.width + deadSpaceGap) * PresContext()->GetPrintPreviewScale(); aDesiredSize.width = w * PresContext()->GetPrintPreviewScale();
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width,
aDesiredSize.height); aDesiredSize.height);
@ -364,8 +365,8 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
// cache the size so we can set the desired size // cache the size so we can set the desired size
// for the other reflows that happen // for the other reflows that happen
mSize.width = aDesiredSize.width; mSize.width = w;
mSize.height = aDesiredSize.height; mSize.height = y;
NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus);
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);

Просмотреть файл

@ -59,6 +59,10 @@
class nsTextPaintStyle; class nsTextPaintStyle;
class PropertyProvider; 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 // This state bit is set on frames that have some non-collapsed characters after
// reflow // reflow
#define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000 #define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
@ -353,9 +357,17 @@ public:
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
PRBool aTrimAfter); PRBool aTrimAfter);
const nsTextFragment* GetFragment() const
{
return !(GetStateBits() & TEXT_BLINK_ON_OR_PRINTING) ?
mContent->GetText() : GetFragmentInternal();
}
protected: protected:
virtual ~nsTextFrame(); virtual ~nsTextFrame();
const nsTextFragment* GetFragmentInternal() const;
nsIFrame* mNextContinuation; nsIFrame* mNextContinuation;
// The key invariant here is that mContentOffset never decreases along // The key invariant here is that mContentOffset never decreases along
// a next-continuation chain. And of course mContentOffset is always <= the // a next-continuation chain. And of course mContentOffset is always <= the

Просмотреть файл

@ -163,8 +163,9 @@
#define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000 #define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000
#define TEXT_WHITESPACE_FLAGS 0x18000000 #define TEXT_WHITESPACE_FLAGS 0x18000000
// This bit is set while the frame is registered as a blinking frame.
#define TEXT_BLINK_ON 0x20000000 // nsTextFrame.h has
// #define TEXT_BLINK_ON_OR_PRINTING 0x20000000
// Set when this text frame is mentioned in the userdata for a textrun // Set when this text frame is mentioned in the userdata for a textrun
#define TEXT_IN_TEXTRUN_USER_DATA 0x40000000 #define TEXT_IN_TEXTRUN_USER_DATA 0x40000000
@ -453,7 +454,7 @@ nsTextFrameTextRunCache::Shutdown() {
PRInt32 nsTextFrame::GetContentEnd() const { PRInt32 nsTextFrame::GetContentEnd() const {
nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation()); nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
return next ? next->GetContentOffset() : mContent->GetText()->GetLength(); return next ? next->GetContentOffset() : GetFragment()->GetLength();
} }
PRInt32 nsTextFrame::GetInFlowContentLength() { PRInt32 nsTextFrame::GetInFlowContentLength() {
@ -698,7 +699,7 @@ public:
PRInt32 GetContentEnd() { PRInt32 GetContentEnd() {
return mEndFrame ? mEndFrame->GetContentOffset() return mEndFrame ? mEndFrame->GetContentOffset()
: mStartFrame->GetContent()->GetText()->GetLength(); : mStartFrame->GetFragment()->GetLength();
} }
}; };
@ -904,7 +905,7 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState
if (textFrame) { if (textFrame) {
if (!aState->mSeenSpaceForLineBreakingOnThisLine) { if (!aState->mSeenSpaceForLineBreakingOnThisLine) {
const nsTextFragment* frag = textFrame->GetContent()->GetText(); const nsTextFragment* frag = textFrame->GetFragment();
PRUint32 start = textFrame->GetContentOffset(); PRUint32 start = textFrame->GetContentOffset();
const void* text = frag->Is2b() const void* text = frag->Is2b()
? static_cast<const void*>(frag->Get2b() + start) ? static_cast<const void*>(frag->Get2b() + start)
@ -1229,7 +1230,7 @@ void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame)
{ {
NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow"); NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow");
mMaxTextLength += aFrame->GetContentLength(); mMaxTextLength += aFrame->GetContentLength();
mDoubleByteText |= aFrame->GetContent()->GetText()->Is2b(); mDoubleByteText |= aFrame->GetFragment()->Is2b();
mLastFrame = aFrame; mLastFrame = aFrame;
mCommonAncestorWithLastFrame = aFrame->GetParent(); mCommonAncestorWithLastFrame = aFrame->GetParent();
@ -1262,7 +1263,7 @@ HasTerminalNewline(const nsTextFrame* aFrame)
{ {
if (aFrame->GetContentLength() == 0) if (aFrame->GetContentLength() == 0)
return PR_FALSE; return PR_FALSE;
const nsTextFragment* frag = aFrame->GetContent()->GetText(); const nsTextFragment* frag = aFrame->GetFragment();
return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n'; return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n';
} }
@ -1589,7 +1590,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
// Figure out what content is included in this flow. // Figure out what content is included in this flow.
nsIContent* content = f->GetContent(); nsIContent* content = f->GetContent();
const nsTextFragment* frag = content->GetText(); const nsTextFragment* frag = f->GetFragment();
PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset(); PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset();
PRInt32 contentEnd = mappedFlow->GetContentEnd(); PRInt32 contentEnd = mappedFlow->GetContentEnd();
PRInt32 contentLength = contentEnd - contentStart; PRInt32 contentLength = contentEnd - contentStart;
@ -1835,7 +1836,7 @@ HasCompressedLeadingWhitespace(nsTextFrame* aFrame, const nsStyleText* aStyleTex
gfxSkipCharsIterator iter = aIterator; gfxSkipCharsIterator iter = aIterator;
PRInt32 frameContentOffset = aFrame->GetContentOffset(); PRInt32 frameContentOffset = aFrame->GetContentOffset();
const nsTextFragment* frag = aFrame->GetContent()->GetText(); const nsTextFragment* frag = aFrame->GetFragment();
while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) { while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) {
if (IsTrimmableSpace(frag, frameContentOffset, aStyleText)) if (IsTrimmableSpace(frag, frameContentOffset, aStyleText))
return PR_TRUE; return PR_TRUE;
@ -2207,7 +2208,7 @@ public:
PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart) PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
: mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull), : mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull),
mTextStyle(aFrame->GetStyleText()), mTextStyle(aFrame->GetStyleText()),
mFrag(aFrame->GetContent()->GetText()), mFrag(aFrame->GetFragment()),
mLineContainer(nsnull), mLineContainer(nsnull),
mFrame(aFrame), mStart(aStart), mTempIterator(aStart), mFrame(aFrame), mStart(aStart), mTempIterator(aStart),
mTabWidths(nsnull), mTabWidths(nsnull),
@ -3331,6 +3332,12 @@ nsTextFrame::Init(nsIContent* aContent,
NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!"); NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT), NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
"Bogus content!"); "Bogus content!");
nsresult rv = nsLayoutUtils::InitTextRunContainerForPrinting(aContent,
this,
TEXT_BLINK_ON_OR_PRINTING);
NS_ENSURE_SUCCESS(rv, rv);
// We're not a continuing frame. // We're not a continuing frame.
// mContentOffset = 0; not necessary since we get zeroed out at init // mContentOffset = 0; not necessary since we get zeroed out at init
return nsFrame::Init(aContent, aParent, aPrevInFlow); return nsFrame::Init(aContent, aParent, aPrevInFlow);
@ -3408,8 +3415,14 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
nsIFrame* aPrevInFlow) nsIFrame* aPrevInFlow)
{ {
NS_ASSERTION(aPrevInFlow, "Must be a continuation!"); NS_ASSERTION(aPrevInFlow, "Must be a continuation!");
nsresult rv = nsLayoutUtils::InitTextRunContainerForPrinting(aContent,
this,
TEXT_BLINK_ON_OR_PRINTING);
NS_ENSURE_SUCCESS(rv, rv);
// NOTE: bypassing nsTextFrame::Init!!! // NOTE: bypassing nsTextFrame::Init!!!
nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow); rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
#ifdef IBMBIDI #ifdef IBMBIDI
nsTextFrame* nextContinuation = nsTextFrame* nextContinuation =
@ -3420,7 +3433,7 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
aPrevInFlow->SetNextInFlow(this); aPrevInFlow->SetNextInFlow(this);
nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow); nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint(); mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint();
NS_ASSERTION(mContentOffset < PRInt32(aContent->GetText()->GetLength()), NS_ASSERTION(mContentOffset < PRInt32(GetFragment()->GetLength()),
"Creating ContinuingTextFrame, but there is no more content"); "Creating ContinuingTextFrame, but there is no more content");
if (prev->GetStyleContext() != GetStyleContext()) { if (prev->GetStyleContext() != GetStyleContext()) {
// We're taking part of prev's text, and its style may be different // We're taking part of prev's text, and its style may be different
@ -3600,7 +3613,7 @@ NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
nsTextFrame::~nsTextFrame() nsTextFrame::~nsTextFrame()
{ {
if (0 != (mState & TEXT_BLINK_ON)) if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic())
{ {
nsBlinkTimer::RemoveBlinkFrame(this); nsBlinkTimer::RemoveBlinkFrame(this);
} }
@ -3784,7 +3797,7 @@ nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame"); DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff() && if ((0 != (mState & TEXT_BLINK_ON_OR_PRINTING)) && nsBlinkTimer::GetBlinkIsOff() &&
PresContext()->IsDynamic()) PresContext()->IsDynamic())
return NS_OK; return NS_OK;
@ -4961,7 +4974,7 @@ nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
if (!mTextRun) if (!mTextRun)
return PR_FALSE; return PR_FALSE;
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_TRUE); TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_TRUE);
// Check whether there are nonskipped characters in the trimmmed range // Check whether there are nonskipped characters in the trimmmed range
return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) > return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
iter.ConvertOriginalToSkipped(trimmed.mStart); iter.ConvertOriginalToSkipped(trimmed.mStart);
@ -5028,7 +5041,7 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
if (!mTextRun) if (!mTextRun)
return PR_FALSE; return PR_FALSE;
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_FALSE); TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_FALSE);
// A negative offset means "end of frame". // A negative offset means "end of frame".
PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset); PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
@ -5143,7 +5156,7 @@ ClusterIterator::ClusterIterator(nsTextFrame* aTextFrame, PRInt32 aPosition,
mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID); mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
mFrag = aTextFrame->GetContent()->GetText(); mFrag = aTextFrame->GetFragment();
mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE); mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE);
PRInt32 textOffset = aTextFrame->GetContentOffset(); PRInt32 textOffset = aTextFrame->GetContentOffset();
@ -5384,7 +5397,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
// Pass null for the line container. This will disable tab spacing, but that's // 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. // OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText(); const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText(); const nsTextFragment* frag = GetFragment();
PropertyProvider provider(mTextRun, textStyle, frag, this, PropertyProvider provider(mTextRun, textStyle, frag, this,
iter, PR_INT32_MAX, nsnull, 0); iter, PR_INT32_MAX, nsnull, 0);
@ -5512,7 +5525,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
// OK since we can't really handle tabs for intrinsic sizing anyway. // OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText(); const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText(); const nsTextFragment* frag = GetFragment();
PropertyProvider provider(mTextRun, textStyle, frag, this, PropertyProvider provider(mTextRun, textStyle, frag, this,
iter, PR_INT32_MAX, nsnull, 0); iter, PR_INT32_MAX, nsnull, 0);
@ -5750,8 +5763,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// Clear out the reflow state flags in mState (without destroying // Clear out the reflow state flags in mState (without destroying
// the TEXT_BLINK_ON bit). We also clear the whitespace flags because this // the TEXT_BLINK_ON_OR_PRINTING bit). We also clear the whitespace flags
// can change whether the frame maps whitespace-only text or not. // because this can change whether the frame maps whitespace-only text or not.
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS); RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
// Temporarily map all possible content while we construct our new textrun. // Temporarily map all possible content while we construct our new textrun.
@ -5773,14 +5786,14 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
nsLineLayout& lineLayout = *aReflowState.mLineLayout; nsLineLayout& lineLayout = *aReflowState.mLineLayout;
if (aReflowState.mFlags.mBlinks) { if (aReflowState.mFlags.mBlinks) {
if (0 == (mState & TEXT_BLINK_ON)) { if (0 == (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState |= TEXT_BLINK_ON; mState |= TEXT_BLINK_ON_OR_PRINTING;
nsBlinkTimer::AddBlinkFrame(aPresContext, this); nsBlinkTimer::AddBlinkFrame(aPresContext, this);
} }
} }
else { else {
if (0 != (mState & TEXT_BLINK_ON)) { if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState &= ~TEXT_BLINK_ON; mState &= ~TEXT_BLINK_ON_OR_PRINTING;
nsBlinkTimer::RemoveBlinkFrame(this); nsBlinkTimer::RemoveBlinkFrame(this);
} }
} }
@ -5795,7 +5808,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
PRUint32 flowEndInTextRun; PRUint32 flowEndInTextRun;
nsIFrame* lineContainer = lineLayout.GetLineContainerFrame(); nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
gfxContext* ctx = aReflowState.rendContext->ThebesContext(); gfxContext* ctx = aReflowState.rendContext->ThebesContext();
const nsTextFragment* frag = mContent->GetText(); const nsTextFragment* frag = GetFragment();
// DOM offsets of the text range we need to measure, after trimming // DOM offsets of the text range we need to measure, after trimming
// whitespace, restricting to first-letter, and restricting preformatted text // whitespace, restricting to first-letter, and restricting preformatted text
@ -6205,7 +6218,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIRenderingContext* aRC)
PRUint32 trimmedStart = start.GetSkippedOffset(); PRUint32 trimmedStart = start.GetSkippedOffset();
const nsTextFragment* frag = mContent->GetText(); const nsTextFragment* frag = GetFragment();
TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE); TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE);
gfxSkipCharsIterator trimmedEndIter = start; gfxSkipCharsIterator trimmedEndIter = start;
const nsStyleText* textStyle = GetStyleText(); const nsStyleText* textStyle = GetStyleText();
@ -6342,7 +6355,7 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
// The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient... // The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
gfxSkipCharsBuilder skipCharsBuilder; gfxSkipCharsBuilder skipCharsBuilder;
nsTextFrame* textFrame; nsTextFrame* textFrame;
const nsTextFragment* textFrag = mContent->GetText(); const nsTextFragment* textFrag = GetFragment();
PRUint32 keptCharsLength = 0; PRUint32 keptCharsLength = 0;
PRUint32 validCharsLength = 0; PRUint32 validCharsLength = 0;
@ -6408,7 +6421,7 @@ void
nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const
{ {
// Get the frames text content // Get the frames text content
const nsTextFragment* frag = mContent->GetText(); const nsTextFragment* frag = GetFragment();
if (!frag) { if (!frag) {
return; return;
} }
@ -6468,7 +6481,7 @@ nsTextFrame::IsEmpty()
return PR_TRUE; return PR_TRUE;
} }
PRBool isEmpty = IsAllWhitespace(mContent->GetText(), PRBool isEmpty = IsAllWhitespace(GetFragment(),
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE); textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE); mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
return isEmpty; return isEmpty;
@ -6605,3 +6618,11 @@ nsTextFrame::IsAtEndOfLine() const
{ {
return (GetStateBits() & TEXT_END_OF_LINE) != 0; return (GetStateBits() & TEXT_END_OF_LINE) != 0;
} }
const nsTextFragment*
nsTextFrame::GetFragmentInternal() const
{
return PresContext()->IsDynamic() ? mContent->GetText() :
static_cast<const nsTextFragment*>(PresContext()->PropertyTable()->
GetProperty(mContent, nsGkAtoms::clonedTextForPrint));
}

Просмотреть файл

@ -54,6 +54,7 @@
#include "gfxMatrix.h" #include "gfxMatrix.h"
#include "gfxPlatform.h" #include "gfxPlatform.h"
#include "gfxTextRunWordCache.h" #include "gfxTextRunWordCache.h"
#include "nsTextFrame.h"
struct CharacterPosition { struct CharacterPosition {
gfxPoint pos; gfxPoint pos;
@ -298,6 +299,11 @@ nsSVGGlyphFrame::Init(nsIContent* aContent,
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT), NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
"trying to construct an SVGGlyphFrame for wrong content element"); "trying to construct an SVGGlyphFrame for wrong content element");
nsresult rv = nsLayoutUtils::InitTextRunContainerForPrinting(aContent,
this,
NS_STATE_SVG_PRINTING);
NS_ENSURE_SUCCESS(rv, rv);
return nsSVGGlyphFrameBase::Init(aContent, aParent, aPrevInFlow); return nsSVGGlyphFrameBase::Init(aContent, aParent, aPrevInFlow);
} }
#endif /* DEBUG */ #endif /* DEBUG */
@ -610,7 +616,7 @@ PRBool
nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData) nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
{ {
nsAutoString characterData; nsAutoString characterData;
mContent->AppendTextTo(characterData); GetFragment()->AppendTo(characterData);
if (mWhitespaceHandling & COMPRESS_WHITESPACE) { if (mWhitespaceHandling & COMPRESS_WHITESPACE) {
PRBool trimLeadingWhitespace, trimTrailingWhitespace; PRBool trimLeadingWhitespace, trimTrailingWhitespace;
@ -762,7 +768,7 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
// The selection ranges are relative to the uncompressed text in // The selection ranges are relative to the uncompressed text in
// the content element. We'll need the text fragment: // the content element. We'll need the text fragment:
const nsTextFragment *fragment = mContent->GetText(); const nsTextFragment* fragment = GetFragment();
NS_ASSERTION(fragment, "no text"); NS_ASSERTION(fragment, "no text");
// get the selection details // get the selection details
@ -1080,7 +1086,7 @@ NS_IMETHODIMP_(PRUint32)
nsSVGGlyphFrame::GetNumberOfChars() nsSVGGlyphFrame::GetNumberOfChars()
{ {
if (mWhitespaceHandling == PRESERVE_WHITESPACE) if (mWhitespaceHandling == PRESERVE_WHITESPACE)
return mContent->TextLength(); return GetFragment()->GetLength();
nsAutoString text; nsAutoString text;
GetCharacterData(text); GetCharacterData(text);

Просмотреть файл

@ -215,6 +215,13 @@ protected:
void SetupGlobalTransform(gfxContext *aContext); void SetupGlobalTransform(gfxContext *aContext);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background); nscolor *foreground, nscolor *background);
const nsTextFragment* GetFragment() const
{
return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?
mContent->GetText() :
static_cast<const nsTextFragment*>(PresContext()->PropertyTable()->
GetProperty(mContent, nsGkAtoms::clonedTextForPrint));
}
// Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting // Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting
gfxTextRun *mTextRun; gfxTextRun *mTextRun;

Просмотреть файл

@ -93,6 +93,9 @@ class nsISVGChildFrame;
#define NS_STATE_SVG_PROPAGATE_TRANSFORM 0x00800000 #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. * Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/ */