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(clickcount, "clickcount")
GK_ATOM(clip, "clip")
GK_ATOM(clonedTextForPrint, "clonedTextForPrint")
GK_ATOM(close, "close")
GK_ATOM(closed, "closed")
GK_ATOM(closemenu, "closemenu")

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

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

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

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

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

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

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

@ -456,6 +456,8 @@ protected:
unsigned mClosingWhilePrinting : 1;
#if NS_PRINT_PREVIEW
unsigned mPrintPreviewZoomed : 1;
// These data members support delayed printing when the document is loading
unsigned mPrintIsPending : 1;
unsigned mPrintDocIsFullyLoaded : 1;
@ -463,6 +465,8 @@ protected:
nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
nsCOMPtr<nsPrintEngine> mPrintEngine;
float mOriginalPrintPreviewScale;
float mPrintPreviewZoom;
#endif // NS_PRINT_PREVIEW
#ifdef NS_DEBUG
@ -536,6 +540,9 @@ void DocumentViewerImpl::PrepareToStartLoad()
DocumentViewerImpl::DocumentViewerImpl()
: mTextZoom(1.0), mPageZoom(1.0),
mIsSticky(PR_TRUE),
#ifdef NS_PRINT_PREVIEW
mPrintPreviewZoom(1.0),
#endif
mHintCharsetSource(kCharsetUninitialized)
{
PrepareToStartLoad();
@ -2722,10 +2729,12 @@ SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure)
NS_IMETHODIMP
DocumentViewerImpl::SetTextZoom(float aTextZoom)
{
if (!GetIsPrintPreview()) {
mTextZoom = aTextZoom;
if (GetIsPrintPreview()) {
return NS_OK;
}
mTextZoom = aTextZoom;
nsIViewManager::UpdateViewBatch batch(GetViewManager());
// 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
DocumentViewerImpl::SetFullZoom(float aFullZoom)
{
if (!GetIsPrintPreview()) {
mPageZoom = aFullZoom;
#ifdef NS_PRINT_PREVIEW
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());
@ -2787,6 +2826,12 @@ NS_IMETHODIMP
DocumentViewerImpl::GetFullZoom(float* 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
// setting for print-preview
nsPresContext* pc = GetPresContext();
@ -3622,6 +3667,7 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings,
}
rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener);
mPrintPreviewZoomed = PR_FALSE;
if (NS_FAILED(rv)) {
OnDonePrinting();
}

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

@ -80,6 +80,7 @@
#include "gfxTypes.h"
#include "gfxUserFontSet.h"
#include "nsTArray.h"
#include "nsTextFragment.h"
#ifdef MOZ_SVG
#include "nsSVGUtils.h"
@ -3175,6 +3176,45 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame)
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,
const nsAString& aValue)
: mContent(aContent),

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

@ -958,6 +958,21 @@ public:
* disabled.
*/
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

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

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

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

@ -766,6 +766,119 @@ struct nsCallbackEventRequest
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;
@ -1198,6 +1311,9 @@ protected:
static PRBool sDisableNonTestMouseEvents;
nsCOMPtr<nsIDocumentObserver> mDocumentObserverForNonDynamicContext;
private:
PRBool InZombieDocument(nsIContent *aContent);
@ -2268,7 +2384,14 @@ NS_IMETHODIMP
PresShell::BeginObservingDocument()
{
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) {
NS_WARNING("Adding a presshell that was disconnected from the document "
"as a document observer? Sounds wrong...");
@ -2286,7 +2409,10 @@ PresShell::EndObservingDocument()
// is gone, perhaps? Except for printing it's NOT gone, sometimes.
mIsDocumentGone = PR_TRUE;
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ?
mDocumentObserverForNonDynamicContext.get() :
this);
mDocumentObserverForNonDynamicContext = nsnull;
}
return NS_OK;
}
@ -3357,6 +3483,10 @@ 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.
@ -4770,6 +4900,9 @@ PresShell::ContentRemoved(nsIDocument *aDocument,
nsresult
PresShell::ReconstructFrames(void)
{
if (!mPresContext || !mPresContext->IsDynamic()) {
return NS_OK;
}
nsAutoScriptBlocker scriptBlocker;
mFrameConstructor->BeginUpdate();
nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();

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

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

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

@ -59,6 +59,10 @@
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
@ -353,9 +357,17 @@ 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

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

@ -163,8 +163,9 @@
#define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000
#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
#define TEXT_IN_TEXTRUN_USER_DATA 0x40000000
@ -453,7 +454,7 @@ nsTextFrameTextRunCache::Shutdown() {
PRInt32 nsTextFrame::GetContentEnd() const {
nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
return next ? next->GetContentOffset() : mContent->GetText()->GetLength();
return next ? next->GetContentOffset() : GetFragment()->GetLength();
}
PRInt32 nsTextFrame::GetInFlowContentLength() {
@ -698,7 +699,7 @@ public:
PRInt32 GetContentEnd() {
return mEndFrame ? mEndFrame->GetContentOffset()
: mStartFrame->GetContent()->GetText()->GetLength();
: mStartFrame->GetFragment()->GetLength();
}
};
@ -904,7 +905,7 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState
if (textFrame) {
if (!aState->mSeenSpaceForLineBreakingOnThisLine) {
const nsTextFragment* frag = textFrame->GetContent()->GetText();
const nsTextFragment* frag = textFrame->GetFragment();
PRUint32 start = textFrame->GetContentOffset();
const void* text = frag->Is2b()
? static_cast<const void*>(frag->Get2b() + start)
@ -1229,7 +1230,7 @@ void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame)
{
NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow");
mMaxTextLength += aFrame->GetContentLength();
mDoubleByteText |= aFrame->GetContent()->GetText()->Is2b();
mDoubleByteText |= aFrame->GetFragment()->Is2b();
mLastFrame = aFrame;
mCommonAncestorWithLastFrame = aFrame->GetParent();
@ -1262,7 +1263,7 @@ HasTerminalNewline(const nsTextFrame* aFrame)
{
if (aFrame->GetContentLength() == 0)
return PR_FALSE;
const nsTextFragment* frag = aFrame->GetContent()->GetText();
const nsTextFragment* frag = aFrame->GetFragment();
return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n';
}
@ -1589,7 +1590,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
// Figure out what content is included in this flow.
nsIContent* content = f->GetContent();
const nsTextFragment* frag = content->GetText();
const nsTextFragment* frag = f->GetFragment();
PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset();
PRInt32 contentEnd = mappedFlow->GetContentEnd();
PRInt32 contentLength = contentEnd - contentStart;
@ -1835,7 +1836,7 @@ HasCompressedLeadingWhitespace(nsTextFrame* aFrame, const nsStyleText* aStyleTex
gfxSkipCharsIterator iter = aIterator;
PRInt32 frameContentOffset = aFrame->GetContentOffset();
const nsTextFragment* frag = aFrame->GetContent()->GetText();
const nsTextFragment* frag = aFrame->GetFragment();
while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) {
if (IsTrimmableSpace(frag, frameContentOffset, aStyleText))
return PR_TRUE;
@ -2207,7 +2208,7 @@ public:
PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
: mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull),
mTextStyle(aFrame->GetStyleText()),
mFrag(aFrame->GetContent()->GetText()),
mFrag(aFrame->GetFragment()),
mLineContainer(nsnull),
mFrame(aFrame), mStart(aStart), mTempIterator(aStart),
mTabWidths(nsnull),
@ -3331,6 +3332,12 @@ nsTextFrame::Init(nsIContent* aContent,
NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
"Bogus content!");
nsresult rv = nsLayoutUtils::InitTextRunContainerForPrinting(aContent,
this,
TEXT_BLINK_ON_OR_PRINTING);
NS_ENSURE_SUCCESS(rv, rv);
// We're not a continuing frame.
// mContentOffset = 0; not necessary since we get zeroed out at init
return nsFrame::Init(aContent, aParent, aPrevInFlow);
@ -3408,8 +3415,14 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
nsIFrame* aPrevInFlow)
{
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!!!
nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
#ifdef IBMBIDI
nsTextFrame* nextContinuation =
@ -3420,7 +3433,7 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
aPrevInFlow->SetNextInFlow(this);
nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
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");
if (prev->GetStyleContext() != GetStyleContext()) {
// 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()
{
if (0 != (mState & TEXT_BLINK_ON))
if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic())
{
nsBlinkTimer::RemoveBlinkFrame(this);
}
@ -3784,7 +3797,7 @@ nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
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())
return NS_OK;
@ -4961,7 +4974,7 @@ nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
if (!mTextRun)
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
return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
iter.ConvertOriginalToSkipped(trimmed.mStart);
@ -5028,7 +5041,7 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
if (!mTextRun)
return PR_FALSE;
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_FALSE);
TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_FALSE);
// A negative offset means "end of frame".
PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
@ -5143,7 +5156,7 @@ ClusterIterator::ClusterIterator(nsTextFrame* aTextFrame, PRInt32 aPosition,
mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
mFrag = aTextFrame->GetContent()->GetText();
mFrag = aTextFrame->GetFragment();
mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE);
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
// OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText();
const nsTextFragment* frag = GetFragment();
PropertyProvider provider(mTextRun, textStyle, frag, this,
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.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText();
const nsTextFragment* frag = GetFragment();
PropertyProvider provider(mTextRun, textStyle, frag, this,
iter, PR_INT32_MAX, nsnull, 0);
@ -5750,8 +5763,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
/////////////////////////////////////////////////////////////////////
// Clear out the reflow state flags in mState (without destroying
// the TEXT_BLINK_ON bit). We also clear the whitespace flags because this
// can change whether the frame maps whitespace-only text or not.
// 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.
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
// Temporarily map all possible content while we construct our new textrun.
@ -5773,14 +5786,14 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
nsLineLayout& lineLayout = *aReflowState.mLineLayout;
if (aReflowState.mFlags.mBlinks) {
if (0 == (mState & TEXT_BLINK_ON)) {
mState |= TEXT_BLINK_ON;
if (0 == (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState |= TEXT_BLINK_ON_OR_PRINTING;
nsBlinkTimer::AddBlinkFrame(aPresContext, this);
}
}
else {
if (0 != (mState & TEXT_BLINK_ON)) {
mState &= ~TEXT_BLINK_ON;
if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
mState &= ~TEXT_BLINK_ON_OR_PRINTING;
nsBlinkTimer::RemoveBlinkFrame(this);
}
}
@ -5795,7 +5808,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
PRUint32 flowEndInTextRun;
nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
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
// whitespace, restricting to first-letter, and restricting preformatted text
@ -6205,7 +6218,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIRenderingContext* aRC)
PRUint32 trimmedStart = start.GetSkippedOffset();
const nsTextFragment* frag = mContent->GetText();
const nsTextFragment* frag = GetFragment();
TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE);
gfxSkipCharsIterator trimmedEndIter = start;
const nsStyleText* textStyle = GetStyleText();
@ -6342,7 +6355,7 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
// The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
gfxSkipCharsBuilder skipCharsBuilder;
nsTextFrame* textFrame;
const nsTextFragment* textFrag = mContent->GetText();
const nsTextFragment* textFrag = GetFragment();
PRUint32 keptCharsLength = 0;
PRUint32 validCharsLength = 0;
@ -6408,7 +6421,7 @@ void
nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const
{
// Get the frames text content
const nsTextFragment* frag = mContent->GetText();
const nsTextFragment* frag = GetFragment();
if (!frag) {
return;
}
@ -6468,7 +6481,7 @@ nsTextFrame::IsEmpty()
return PR_TRUE;
}
PRBool isEmpty = IsAllWhitespace(mContent->GetText(),
PRBool isEmpty = IsAllWhitespace(GetFragment(),
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
return isEmpty;
@ -6605,3 +6618,11 @@ nsTextFrame::IsAtEndOfLine() const
{
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 "gfxPlatform.h"
#include "gfxTextRunWordCache.h"
#include "nsTextFrame.h"
struct CharacterPosition {
gfxPoint pos;
@ -298,6 +299,11 @@ nsSVGGlyphFrame::Init(nsIContent* aContent,
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
"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);
}
#endif /* DEBUG */
@ -610,7 +616,7 @@ PRBool
nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
{
nsAutoString characterData;
mContent->AppendTextTo(characterData);
GetFragment()->AppendTo(characterData);
if (mWhitespaceHandling & COMPRESS_WHITESPACE) {
PRBool trimLeadingWhitespace, trimTrailingWhitespace;
@ -762,7 +768,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 = mContent->GetText();
const nsTextFragment* fragment = GetFragment();
NS_ASSERTION(fragment, "no text");
// get the selection details
@ -1080,7 +1086,7 @@ NS_IMETHODIMP_(PRUint32)
nsSVGGlyphFrame::GetNumberOfChars()
{
if (mWhitespaceHandling == PRESERVE_WHITESPACE)
return mContent->TextLength();
return GetFragment()->GetLength();
nsAutoString text;
GetCharacterData(text);

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

@ -215,6 +215,13 @@ protected:
void SetupGlobalTransform(gfxContext *aContext);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
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
gfxTextRun *mTextRun;

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

@ -93,6 +93,9 @@ class nsISVGChildFrame;
#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.
*/