1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is the Mozilla SVG project.
17
* The Initial Developer of the Original Code is
18
* Crocodile Clips Ltd..
19
* Portions created by the Initial Developer are Copyright (C) 2001
20
* the Initial Developer. All Rights Reserved.
23
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
25
* Alternatively, the contents of this file may be used under the terms of
26
* either of the GNU General Public License Version 2 or later (the "GPL"),
27
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the MPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
40
#include "nsISVGChildFrame.h"
41
#include "nsSVGOuterSVGFrame.h"
42
#include "nsIDOMSVGAnimatedRect.h"
43
#include "nsSVGMatrix.h"
44
#include "nsSVGSVGElement.h"
45
#include "nsSVGContainerFrame.h"
46
#include "gfxContext.h"
48
typedef nsSVGDisplayContainerFrame nsSVGInnerSVGFrameBase;
50
class nsSVGInnerSVGFrame : public nsSVGInnerSVGFrameBase,
51
public nsISVGValueObserver,
55
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
57
nsSVGInnerSVGFrame(nsStyleContext* aContext) :
58
nsSVGInnerSVGFrameBase(aContext), mPropagateTransform(PR_TRUE) {}
60
// nsISupports interface:
61
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
63
NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
64
NS_IMETHOD_(nsrefcnt) Release() { return 1; }
68
NS_IMETHOD DidSetStyleContext();
70
// We don't define an AttributeChanged method since changes to the
71
// 'x', 'y', 'width' and 'height' attributes of our content object
72
// are handled in nsSVGSVGElement::DidModifySVGObservable
75
* Get the "type" of the frame
77
* @see nsGkAtoms::svgInnerSVGFrame
79
virtual nsIAtom* GetType() const;
82
NS_IMETHOD GetFrameName(nsAString& aResult) const
84
return MakeFrameName(NS_LITERAL_STRING("SVGInnerSVG"), aResult);
88
// nsISVGChildFrame interface:
89
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
90
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
91
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
92
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
93
virtual already_AddRefed<nsIDOMSVGMatrix> GetOverrideCTM();
94
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
96
// nsSVGContainerFrame methods:
97
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
99
// nsISVGValueObserver
100
NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
101
nsISVGValue::modificationType aModType);
102
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
103
nsISVGValue::modificationType aModType);
105
// nsISupportsWeakReference
106
// implementation inherited from nsSupportsWeakReference
108
// nsISVGSVGFrame interface:
109
NS_IMETHOD SuspendRedraw();
110
NS_IMETHOD UnsuspendRedraw();
111
NS_IMETHOD NotifyViewportChange();
115
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
116
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
118
PRPackedBool mPropagateTransform;
121
//----------------------------------------------------------------------
125
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
127
nsCOMPtr<nsIDOMSVGSVGElement> svg = do_QueryInterface(aContent);
129
NS_ERROR("Can't create frame! Content is not an SVG 'svg' element!");
133
return new (aPresShell) nsSVGInnerSVGFrame(aContext);
136
//----------------------------------------------------------------------
137
// nsISupports methods
139
NS_INTERFACE_MAP_BEGIN(nsSVGInnerSVGFrame)
140
NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
141
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
142
NS_INTERFACE_MAP_ENTRY(nsISVGSVGFrame)
143
NS_INTERFACE_MAP_END_INHERITING(nsSVGInnerSVGFrameBase)
146
//----------------------------------------------------------------------
150
nsSVGInnerSVGFrame::GetType() const
152
return nsGkAtoms::svgInnerSVGFrame;
155
//----------------------------------------------------------------------
156
// nsISVGChildFrame methods
159
nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
163
gfxContext *gfx = aContext->GetGfxContext();
167
if (GetStyleDisplay()->IsScrollableOverflow()) {
168
nsCOMPtr<nsIDOMSVGMatrix> clipTransform;
169
if (!mPropagateTransform) {
170
NS_NewSVGMatrix(getter_AddRefs(clipTransform));
172
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>
174
clipTransform = parent->GetCanvasTM();
178
nsSVGSVGElement *svg = static_cast<nsSVGSVGElement*>(mContent);
180
float x, y, width, height;
181
svg->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
183
nsSVGUtils::SetClipRect(gfx, clipTransform, x, y, width, height);
187
rv = nsSVGInnerSVGFrameBase::PaintSVG(aContext, aDirtyRect);
195
nsSVGInnerSVGFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation)
197
// make sure our cached transform matrix gets (lazily) updated
200
return nsSVGInnerSVGFrameBase::NotifyCanvasTMChanged(suppressInvalidation);
204
nsSVGInnerSVGFrame::SetMatrixPropagation(PRBool aPropagate)
206
mPropagateTransform = aPropagate;
211
nsSVGInnerSVGFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM)
217
already_AddRefed<nsIDOMSVGMatrix>
218
nsSVGInnerSVGFrame::GetOverrideCTM()
220
nsIDOMSVGMatrix *matrix = mOverrideCTM.get();
221
NS_IF_ADDREF(matrix);
226
nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
228
if (GetStyleDisplay()->IsScrollableOverflow()) {
229
float clipX, clipY, clipWidth, clipHeight;
230
nsCOMPtr<nsIDOMSVGMatrix> clipTransform;
232
nsSVGElement *svg = static_cast<nsSVGElement*>(mContent);
233
svg->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull);
235
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>
237
clipTransform = parent->GetCanvasTM();
239
if (!nsSVGUtils::HitTestRect(clipTransform,
240
clipX, clipY, clipWidth, clipHeight,
247
return nsSVGInnerSVGFrameBase::GetFrameForPointSVG(x, y, hit);
250
//----------------------------------------------------------------------
251
// nsISVGSVGFrame methods:
254
nsSVGInnerSVGFrame::SuspendRedraw()
256
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
257
if (!outerSVGFrame) {
258
NS_ERROR("no outer svg frame");
259
return NS_ERROR_FAILURE;
261
return outerSVGFrame->SuspendRedraw();
265
nsSVGInnerSVGFrame::UnsuspendRedraw()
267
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
268
if (!outerSVGFrame) {
269
NS_ERROR("no outer svg frame");
270
return NS_ERROR_FAILURE;
272
return outerSVGFrame->UnsuspendRedraw();
276
nsSVGInnerSVGFrame::NotifyViewportChange()
278
// make sure canvas transform matrix gets (lazily) recalculated:
283
nsIFrame* kid = mFrames.FirstChild();
285
nsISVGChildFrame* SVGFrame = nsnull;
286
CallQueryInterface(kid, &SVGFrame);
288
SVGFrame->NotifyCanvasTMChanged(PR_FALSE);
289
kid = kid->GetNextSibling();
295
//----------------------------------------------------------------------
296
// nsSVGContainerFrame methods:
298
already_AddRefed<nsIDOMSVGMatrix>
299
nsSVGInnerSVGFrame::GetCanvasTM()
301
if (!mPropagateTransform) {
302
nsIDOMSVGMatrix *retval;
304
retval = mOverrideCTM;
307
NS_NewSVGMatrix(&retval);
312
// parentTM * Translate(x,y) * viewboxToViewportTM
315
// get the transform from our parent's coordinate system to ours:
316
NS_ASSERTION(mParent, "null parent");
317
nsSVGContainerFrame *containerFrame = static_cast<nsSVGContainerFrame*>
319
nsCOMPtr<nsIDOMSVGMatrix> parentTM = containerFrame->GetCanvasTM();
320
NS_ASSERTION(parentTM, "null TM");
322
// append the transform due to the 'x' and 'y' attributes:
324
nsSVGSVGElement *svg = static_cast<nsSVGSVGElement*>(mContent);
325
svg->GetAnimatedLengthValues(&x, &y, nsnull);
327
nsCOMPtr<nsIDOMSVGMatrix> xyTM;
328
parentTM->Translate(x, y, getter_AddRefs(xyTM));
330
// append the viewbox to viewport transform:
331
nsCOMPtr<nsIDOMSVGMatrix> viewBoxToViewportTM;
332
nsSVGSVGElement *svgElement = static_cast<nsSVGSVGElement*>(mContent);
333
svgElement->GetViewboxToViewportTransform(getter_AddRefs(viewBoxToViewportTM));
334
xyTM->Multiply(viewBoxToViewportTM, getter_AddRefs(mCanvasTM));
337
nsIDOMSVGMatrix* retval = mCanvasTM.get();
338
NS_IF_ADDREF(retval);
342
//----------------------------------------------------------------------
343
// nsISVGValueObserver methods:
346
nsSVGInnerSVGFrame::WillModifySVGObservable(nsISVGValue* observable,
347
nsISVGValue::modificationType aModType)
353
nsSVGInnerSVGFrame::DidModifySVGObservable (nsISVGValue* observable,
354
nsISVGValue::modificationType aModType)
356
NotifyViewportChange();
361
nsSVGInnerSVGFrame::DidSetStyleContext()
363
nsSVGUtils::StyleEffects(this);