00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "nsContainerFrame.h"
00040 #include "nsIDOMSVGGElement.h"
00041 #include "nsIPresContext.h"
00042 #include "nsISVGChildFrame.h"
00043 #include "nsISVGContainerFrame.h"
00044 #include "nsISVGRendererCanvas.h"
00045 #include "nsWeakReference.h"
00046 #include "nsISVGValue.h"
00047 #include "nsISVGValueObserver.h"
00048 #include "nsISVGOuterSVGFrame.h"
00049
00050 typedef nsContainerFrame nsSVGGenericContainerFrameBase;
00051
00052 class nsSVGGenericContainerFrame : public nsSVGGenericContainerFrameBase,
00053 public nsISVGChildFrame,
00054 public nsISVGContainerFrame,
00055 public nsISVGValueObserver,
00056 public nsSupportsWeakReference
00057
00058 {
00059 friend nsresult
00060 NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00061 protected:
00062 nsSVGGenericContainerFrame();
00063 virtual ~nsSVGGenericContainerFrame();
00064 nsresult Init();
00065
00066
00067 NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
00068 private:
00069 NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
00070 NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
00071 public:
00072
00073
00074 NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
00075 nsIPresShell& aPresShell,
00076 nsIAtom* aListName,
00077 nsIFrame* aFrameList);
00078 NS_IMETHOD InsertFrames(nsIPresContext* aPresContext,
00079 nsIPresShell& aPresShell,
00080 nsIAtom* aListName,
00081 nsIFrame* aPrevFrame,
00082 nsIFrame* aFrameList);
00083 NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext,
00084 nsIPresShell& aPresShell,
00085 nsIAtom* aListName,
00086 nsIFrame* aOldFrame);
00087 NS_IMETHOD ReplaceFrame(nsIPresContext* aPresContext,
00088 nsIPresShell& aPresShell,
00089 nsIAtom* aListName,
00090 nsIFrame* aOldFrame,
00091 nsIFrame* aNewFrame);
00092 NS_IMETHOD Init(nsIPresContext* aPresContext,
00093 nsIContent* aContent,
00094 nsIFrame* aParent,
00095 nsStyleContext* aContext,
00096 nsIFrame* aPrevInFlow);
00097
00098 NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
00099 nsIContent* aChild,
00100 PRInt32 aNameSpaceID,
00101 nsIAtom* aAttribute,
00102 PRInt32 aModType);
00103
00104
00105 NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable);
00106 NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable);
00107
00108
00109
00110
00111
00112 NS_IMETHOD Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips);
00113 NS_IMETHOD GetFrameForPoint(float x, float y, nsIFrame** hit);
00114 NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
00115 NS_IMETHOD InitialUpdate();
00116 NS_IMETHOD NotifyCTMChanged();
00117 NS_IMETHOD NotifyRedrawSuspended();
00118 NS_IMETHOD NotifyRedrawUnsuspended();
00119 NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
00120
00121
00122 NS_IMETHOD_(nsISVGOuterSVGFrame*) GetOuterSVGFrame();
00123
00124 protected:
00125 };
00126
00127
00128
00129
00130 nsresult
00131 NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame)
00132 {
00133 nsSVGGenericContainerFrame* it = new (aPresShell) nsSVGGenericContainerFrame;
00134 if (nsnull == it)
00135 return NS_ERROR_OUT_OF_MEMORY;
00136
00137 *aNewFrame = it;
00138
00139 return NS_OK;
00140 }
00141
00142 nsSVGGenericContainerFrame::nsSVGGenericContainerFrame()
00143 {
00144 #ifdef DEBUG
00145
00146 #endif
00147 }
00148
00149 nsSVGGenericContainerFrame::~nsSVGGenericContainerFrame()
00150 {
00151 #ifdef DEBUG
00152
00153 #endif
00154 }
00155
00156 nsresult nsSVGGenericContainerFrame::Init()
00157 {
00158 return NS_OK;
00159 }
00160
00161
00162
00163
00164 NS_INTERFACE_MAP_BEGIN(nsSVGGenericContainerFrame)
00165 NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
00166 NS_INTERFACE_MAP_ENTRY(nsISVGContainerFrame)
00167 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
00168 NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
00169 NS_INTERFACE_MAP_END_INHERITING(nsSVGGenericContainerFrameBase)
00170
00171
00172
00173
00174 NS_IMETHODIMP
00175 nsSVGGenericContainerFrame::Init(nsIPresContext* aPresContext,
00176 nsIContent* aContent,
00177 nsIFrame* aParent,
00178 nsStyleContext* aContext,
00179 nsIFrame* aPrevInFlow)
00180 {
00181 nsresult rv;
00182 rv = nsSVGGenericContainerFrameBase::Init(aPresContext, aContent, aParent,
00183 aContext, aPrevInFlow);
00184
00185 Init();
00186
00187 return rv;
00188 }
00189
00190
00191 NS_IMETHODIMP
00192 nsSVGGenericContainerFrame::AppendFrames(nsIPresContext* aPresContext,
00193 nsIPresShell& aPresShell,
00194 nsIAtom* aListName,
00195 nsIFrame* aFrameList)
00196 {
00197
00198 return InsertFrames(aPresContext, aPresShell, aListName,
00199 mFrames.LastChild(), aFrameList);
00200 }
00201
00202 NS_IMETHODIMP
00203 nsSVGGenericContainerFrame::InsertFrames(nsIPresContext* aPresContext,
00204 nsIPresShell& aPresShell,
00205 nsIAtom* aListName,
00206 nsIFrame* aPrevFrame,
00207 nsIFrame* aFrameList)
00208 {
00209 nsIFrame* lastNewFrame = nsnull;
00210 {
00211 nsFrameList tmpList(aFrameList);
00212 lastNewFrame = tmpList.LastChild();
00213 }
00214
00215
00216 mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
00217
00218
00219 nsIFrame* end = nsnull;
00220 if (lastNewFrame)
00221 end = lastNewFrame->GetNextSibling();
00222
00223 for (nsIFrame*kid=aFrameList; kid != end; kid = kid->GetNextSibling()) {
00224 nsISVGChildFrame* SVGFrame=nsnull;
00225 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00226 if (SVGFrame) {
00227 SVGFrame->InitialUpdate();
00228 }
00229 }
00230
00231 return NS_OK;
00232 }
00233
00234 NS_IMETHODIMP
00235 nsSVGGenericContainerFrame::RemoveFrame(nsIPresContext* aPresContext,
00236 nsIPresShell& aPresShell,
00237 nsIAtom* aListName,
00238 nsIFrame* aOldFrame)
00239 {
00240 nsCOMPtr<nsISVGRendererRegion> dirty_region;
00241
00242 nsISVGChildFrame* SVGFrame=nsnull;
00243 aOldFrame->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00244
00245 if (SVGFrame)
00246 dirty_region = SVGFrame->GetCoveredRegion();
00247
00248 PRBool result = mFrames.DestroyFrame(aPresContext, aOldFrame);
00249
00250 nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00251 NS_ASSERTION(outerSVGFrame, "no outer svg frame");
00252 if (dirty_region && outerSVGFrame)
00253 outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
00254
00255 NS_ASSERTION(result, "didn't find frame to delete");
00256 return result ? NS_OK : NS_ERROR_FAILURE;
00257 }
00258
00259 NS_IMETHODIMP
00260 nsSVGGenericContainerFrame::ReplaceFrame(nsIPresContext* aPresContext,
00261 nsIPresShell& aPresShell,
00262 nsIAtom* aListName,
00263 nsIFrame* aOldFrame,
00264 nsIFrame* aNewFrame)
00265 {
00266 NS_NOTYETIMPLEMENTED("write me!");
00267 return NS_ERROR_UNEXPECTED;
00268 }
00269
00270 NS_IMETHODIMP
00271 nsSVGGenericContainerFrame::AttributeChanged(nsIPresContext* aPresContext,
00272 nsIContent* aChild,
00273 PRInt32 aNameSpaceID,
00274 nsIAtom* aAttribute,
00275 PRInt32 aModType)
00276 {
00277 #ifdef DEBUG
00278 nsAutoString str;
00279 aAttribute->ToString(str);
00280 printf("** nsSVGGenericContainerFrame::AttributeChanged(%s)\n",
00281 NS_LossyConvertUCS2toASCII(str).get());
00282 #endif
00283
00284 return NS_OK;
00285 }
00286
00287
00288
00289
00290
00291 NS_IMETHODIMP
00292 nsSVGGenericContainerFrame::WillModifySVGObservable(nsISVGValue* observable)
00293 {
00294 return NS_OK;
00295 }
00296
00297
00298 NS_IMETHODIMP
00299 nsSVGGenericContainerFrame::DidModifySVGObservable(nsISVGValue* observable)
00300 {
00301 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00302 kid = kid->GetNextSibling()) {
00303 nsISVGChildFrame* SVGFrame=nsnull;
00304 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00305 if (SVGFrame)
00306 SVGFrame->NotifyCTMChanged();
00307 }
00308 return NS_OK;
00309 }
00310
00311
00312
00313
00314
00315 NS_IMETHODIMP
00316 nsSVGGenericContainerFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
00317 {
00318 #ifdef DEBUG
00319
00320 #endif
00321 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00322 kid = kid->GetNextSibling()) {
00323 nsISVGChildFrame* SVGFrame=nsnull;
00324 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00325 if (SVGFrame)
00326 SVGFrame->Paint(canvas, dirtyRectTwips);
00327 }
00328
00329 return NS_OK;
00330 }
00331
00332 NS_IMETHODIMP
00333 nsSVGGenericContainerFrame::GetFrameForPoint(float x, float y, nsIFrame** hit)
00334 {
00335 #ifdef DEBUG
00336
00337 #endif
00338 *hit = nsnull;
00339 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00340 kid = kid->GetNextSibling()) {
00341 nsISVGChildFrame* SVGFrame=nsnull;
00342 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00343 if (SVGFrame) {
00344 nsIFrame* temp=nsnull;
00345 nsresult rv = SVGFrame->GetFrameForPoint(x, y, &temp);
00346 if (NS_SUCCEEDED(rv) && temp) {
00347 *hit = temp;
00348
00349
00350 }
00351 }
00352 }
00353
00354 return *hit ? NS_OK : NS_ERROR_FAILURE;
00355 }
00356
00357 NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
00358 nsSVGGenericContainerFrame::GetCoveredRegion()
00359 {
00360 nsISVGRendererRegion *accu_region=nsnull;
00361
00362 nsIFrame* kid = mFrames.FirstChild();
00363 while (kid) {
00364 nsISVGChildFrame* SVGFrame=0;
00365 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00366 if (SVGFrame) {
00367 nsCOMPtr<nsISVGRendererRegion> dirty_region = SVGFrame->GetCoveredRegion();
00368 if (dirty_region) {
00369 if (accu_region) {
00370 nsCOMPtr<nsISVGRendererRegion> temp = dont_AddRef(accu_region);
00371 dirty_region->Combine(temp, &accu_region);
00372 }
00373 else {
00374 accu_region = dirty_region;
00375 NS_IF_ADDREF(accu_region);
00376 }
00377 }
00378 }
00379 kid->GetNextSibling(&kid);
00380 }
00381
00382 return accu_region;
00383 }
00384
00385 NS_IMETHODIMP
00386 nsSVGGenericContainerFrame::InitialUpdate()
00387 {
00388 nsIFrame* kid = mFrames.FirstChild();
00389 while (kid) {
00390 nsISVGChildFrame* SVGFrame=0;
00391 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00392 if (SVGFrame) {
00393 SVGFrame->InitialUpdate();
00394 }
00395 kid->GetNextSibling(&kid);
00396 }
00397 return NS_OK;
00398 }
00399
00400 NS_IMETHODIMP
00401 nsSVGGenericContainerFrame::NotifyCTMChanged()
00402 {
00403 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00404 kid = kid->GetNextSibling()) {
00405 nsISVGChildFrame* SVGFrame=nsnull;
00406 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00407 if (SVGFrame) {
00408 SVGFrame->NotifyCTMChanged();
00409 }
00410 }
00411 return NS_OK;
00412 }
00413
00414 NS_IMETHODIMP
00415 nsSVGGenericContainerFrame::NotifyRedrawSuspended()
00416 {
00417 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00418 kid = kid->GetNextSibling()) {
00419 nsISVGChildFrame* SVGFrame=0;
00420 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00421 if (SVGFrame) {
00422 SVGFrame->NotifyRedrawSuspended();
00423 }
00424 }
00425 return NS_OK;
00426 }
00427
00428 NS_IMETHODIMP
00429 nsSVGGenericContainerFrame::NotifyRedrawUnsuspended()
00430 {
00431 for (nsIFrame* kid = mFrames.FirstChild(); kid;
00432 kid = kid->GetNextSibling()) {
00433 nsISVGChildFrame* SVGFrame=nsnull;
00434 kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00435 if (SVGFrame) {
00436 SVGFrame->NotifyRedrawUnsuspended();
00437 }
00438 }
00439 return NS_OK;
00440 }
00441
00442 NS_IMETHODIMP
00443 nsSVGGenericContainerFrame::GetBBox(nsIDOMSVGRect **_retval)
00444 {
00445 *_retval = nsnull;
00446 return NS_ERROR_FAILURE;
00447 }
00448
00449
00450
00451
00452 NS_IMETHODIMP_(nsISVGOuterSVGFrame *)
00453 nsSVGGenericContainerFrame::GetOuterSVGFrame()
00454 {
00455 NS_ASSERTION(mParent, "null parent");
00456
00457 nsISVGContainerFrame *containerFrame;
00458 mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
00459 if (!containerFrame) {
00460 NS_ERROR("invalid container");
00461 return nsnull;
00462 }
00463
00464 return containerFrame->GetOuterSVGFrame();
00465 }