Bug 319786 - implement xml:space handling. r=tor,sr=roc

This commit is contained in:
longsonr%gmail.com 2006-09-28 08:00:20 +00:00
Родитель 2354bf17ad
Коммит 27faef4977
12 изменённых файлов: 156 добавлений и 12 удалений

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

@ -86,6 +86,12 @@ nsSVGForeignObjectFrame::nsSVGForeignObjectFrame(nsStyleContext* aContext)
{
}
void nsSVGForeignObjectFrame::Destroy()
{
nsSVGUtils::StyleEffects(this);
nsSVGForeignObjectFrameBase::Destroy();
}
//----------------------------------------------------------------------
// nsISupports methods

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

@ -60,6 +60,7 @@ class nsSVGForeignObjectFrame : public nsSVGForeignObjectFrameBase,
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
protected:
nsSVGForeignObjectFrame(nsStyleContext* aContext);
virtual void Destroy();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);

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

@ -72,6 +72,12 @@ NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext*
return new (aPresShell) nsSVGGFrame(aContext);
}
void nsSVGGFrame::Destroy()
{
nsSVGUtils::StyleEffects(this);
nsSVGGFrameBase::Destroy();
}
nsIAtom *
nsSVGGFrame::GetType() const
{

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

@ -54,6 +54,7 @@ class nsSVGGFrame : public nsSVGGFrameBase,
public:
nsSVGGFrame(nsStyleContext* aContext) :
nsSVGGFrameBase(aContext), mPropagateTransform(PR_TRUE) {}
virtual void Destroy();
/**
* Get the "type" of the frame

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

@ -536,6 +536,15 @@ nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
trimTrailingWhitespace = ((mWhitespaceHandling & TRIM_TRAILING_WHITESPACE) != 0);
characterData.CompressWhitespace(trimLeadingWhitespace,
trimTrailingWhitespace);
} else {
nsAString::iterator start, end;
characterData.BeginWriting(start);
characterData.EndWriting(end);
while (start != end) {
if (NS_IsAsciiWhitespace(*start))
*start = ' ';
++start;
}
}
aCharacterData = characterData;

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

@ -57,6 +57,7 @@ class nsSVGInnerSVGFrame : public nsSVGInnerSVGFrameBase,
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
protected:
nsSVGInnerSVGFrame(nsStyleContext* aContext);
virtual void Destroy();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@ -138,6 +139,12 @@ nsSVGInnerSVGFrame::nsSVGInnerSVGFrame(nsStyleContext* aContext) :
#endif
}
void nsSVGInnerSVGFrame::Destroy()
{
nsSVGUtils::StyleEffects(this);
nsSVGInnerSVGFrameBase::Destroy();
}
void
nsSVGInnerSVGFrame::UpdateCoordCtx()
{

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

@ -40,18 +40,104 @@
#include "nsIDOMSVGSVGElement.h"
#include "nsISVGRenderer.h"
#include "nsSVGSVGElement.h"
#include "nsSVGTextFrame.h"
#include "nsIServiceManager.h"
#include "nsIViewManager.h"
#include "nsReflowPath.h"
#include "nsSVGRect.h"
#include "nsDisplayList.h"
#include "nsISVGRendererCanvas.h"
#include "nsStubMutationObserver.h"
#if defined(DEBUG) && defined(SVG_DEBUG_PRINTING)
#include "nsIDeviceContext.h"
#include "nsTransform2D.h"
#endif
class nsSVGMutationObserver : public nsStubMutationObserver
{
public:
// nsIMutationObserver interface
void AttributeChanged(nsIDocument *aDocument,
nsIContent *aContent,
PRInt32 aNameSpaceID,
nsIAtom *aAttribute,
PRInt32 aModType);
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
NS_IMETHOD_(nsrefcnt) Release() { return 1; }
static void UpdateTextFragmentTrees(nsIFrame *aFrame);
};
//----------------------------------------------------------------------
// nsISupports methods
NS_INTERFACE_MAP_BEGIN(nsSVGMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_END
static nsSVGMutationObserver sSVGMutationObserver;
//----------------------------------------------------------------------
// nsIMutationObserver methods
void
nsSVGMutationObserver::AttributeChanged(nsIDocument *aDocument,
nsIContent *aContent,
PRInt32 aNameSpaceID,
nsIAtom *aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID != kNameSpaceID_XML || aAttribute != nsGkAtoms::space) {
return;
}
PRUint32 count = aDocument->GetNumberOfShells();
for (PRUint32 i = 0; i < count; ++i) {
nsIFrame *frame = aDocument->GetShellAt(i)->GetPrimaryFrameFor(aContent);
if (!frame) {
continue;
}
// is the content a child of a text element
nsISVGTextContentMetrics* metrics;
CallQueryInterface(frame, &metrics);
if (metrics) {
nsSVGTextFrame* textFrame = NS_STATIC_CAST(nsSVGTextContainerFrame*,
frame)->GetTextFrame();
if (!textFrame->IsGlyphFragmentTreeSuspended())
textFrame->UpdateFragmentTree();
continue;
}
// if not, are there text elements amongst its descendents
UpdateTextFragmentTrees(frame);
}
}
//----------------------------------------------------------------------
// Implementation helpers
void
nsSVGMutationObserver::UpdateTextFragmentTrees(nsIFrame *aFrame)
{
nsIFrame* kid = aFrame->GetFirstChild(nsnull);
while (kid) {
if (kid->GetType() == nsLayoutAtoms::svgTextFrame) {
nsSVGTextFrame* textFrame = NS_STATIC_CAST(nsSVGTextFrame*, kid);
if (!textFrame->IsGlyphFragmentTreeSuspended()) {
textFrame->UpdateFragmentTree();
}
} else {
UpdateTextFragmentTrees(kid);
}
kid = kid->GetNextSibling();
}
}
//----------------------------------------------------------------------
// Implementation
@ -77,6 +163,14 @@ nsSVGOuterSVGFrame::nsSVGOuterSVGFrame(nsStyleContext* aContext)
{
}
nsSVGOuterSVGFrame::~nsSVGOuterSVGFrame()
{
nsIDocument *doc = mContent->GetOwnerDoc();
if (doc) {
doc->RemoveMutationObserver(&sSVGMutationObserver);
}
}
NS_IMETHODIMP
nsSVGOuterSVGFrame::InitSVG()
{
@ -96,12 +190,15 @@ nsSVGOuterSVGFrame::InitSVG()
NS_ASSERTION(SVGElement, "wrong content element");
SVGElement->SetParentCoordCtxProvider(this);
// we only care about our content's zoom and pan values if it's the root element
nsIDocument* doc = mContent->GetCurrentDoc();
if (doc && doc->GetRootContent() == mContent) {
SVGElement->GetZoomAndPanEnum(getter_AddRefs(mZoomAndPan));
SVGElement->GetCurrentTranslate(getter_AddRefs(mCurrentTranslate));
SVGElement->GetCurrentScaleNumber(getter_AddRefs(mCurrentScale));
if (doc) {
// we only care about our content's zoom and pan values if it's the root element
if (doc->GetRootContent() == mContent) {
SVGElement->GetZoomAndPanEnum(getter_AddRefs(mZoomAndPan));
SVGElement->GetCurrentTranslate(getter_AddRefs(mCurrentTranslate));
SVGElement->GetCurrentScaleNumber(getter_AddRefs(mCurrentScale));
}
doc->AddMutationObserver(&sSVGMutationObserver);
}
SuspendRedraw();

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

@ -61,6 +61,7 @@ class nsSVGOuterSVGFrame : public nsSVGOuterSVGFrameBase,
NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
protected:
nsSVGOuterSVGFrame(nsStyleContext* aContext);
virtual ~nsSVGOuterSVGFrame();
NS_IMETHOD InitSVG();
// nsISupports interface:

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

@ -64,7 +64,7 @@ class nsSVGPathGeometryFrame : public nsSVGPathGeometryFrameBase,
{
public:
nsSVGPathGeometryFrame(nsStyleContext* aContext);
virtual ~nsSVGPathGeometryFrame();
~nsSVGPathGeometryFrame();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@ -127,6 +127,7 @@ protected:
private:
void Render(nsISVGRendererCanvas *aCanvas);
void GeneratePath(cairo_t *ctx, nsISVGCairoCanvas* aCanvas);
void RemovePathProperties();
/*
* Check for what cairo returns for the fill extents of a degenerate path

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

@ -72,7 +72,7 @@ nsSVGTextContainerFrame::GetX()
return nsnull;
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::x))
return nsnull;
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList;
tpElement->GetX(getter_AddRefs(animLengthList));
@ -91,7 +91,7 @@ nsSVGTextContainerFrame::GetY()
return nsnull;
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::y))
return nsnull;
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList;
tpElement->GetY(getter_AddRefs(animLengthList));
@ -311,8 +311,24 @@ nsSVGTextContainerFrame::SetWhitespaceHandling()
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode* next;
// XXX should inspect xml:space
PRUint8 whitespaceHandling = (COMPRESS_WHITESPACE | TRIM_LEADING_WHITESPACE);
PRUint8 whitespaceHandling = COMPRESS_WHITESPACE | TRIM_LEADING_WHITESPACE;
for (nsIFrame *frame = this; frame != nsnull; frame = frame->GetParent()) {
nsIContent *content = frame->GetContent();
static nsIContent::AttrValuesArray strings[] =
{&nsGkAtoms::preserve, &nsGkAtoms::_default, nsnull};
PRInt32 index = content->FindAttrValueIn(kNameSpaceID_XML,
nsGkAtoms::space,
strings, eCaseMatters);
if (index == 0) {
whitespaceHandling = PRESERVE_WHITESPACE;
break;
}
if (index != nsIContent::ATTR_MISSING ||
(frame->GetStateBits() & NS_STATE_IS_OUTER_SVG))
break;
}
while (node) {
next = GetNextGlyphFragmentChildNode(node);

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

@ -119,10 +119,10 @@ public:
void NotifyGlyphFragmentTreeChange(nsISVGGlyphFragmentNode* caller);
PRBool IsMetricsSuspended();
PRBool IsGlyphFragmentTreeSuspended();
void UpdateFragmentTree();
private:
void EnsureFragmentTreeUpToDate();
void UpdateFragmentTree();
void UpdateGlyphPositioning();
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;

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

@ -59,7 +59,6 @@
#include "nsISVGRenderer.h"
#include "nsSVGFilterFrame.h"
#include "nsINameSpaceManager.h"
#include "nsISVGChildFrame.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGPoint.h"
#include "nsDOMError.h"