/layout/svg/base/src/nsSVGGenericContainerFrame.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ----- BEGIN LICENSE BLOCK -----
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License
00006  * Version 1.1 (the "License"); you may not use this file except in
00007  * compliance with the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla SVG project.
00016  *
00017  * The Initial Developer of the Original Code is 
00018  * Crocodile Clips Ltd..
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *    Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or 
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the NPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ----- END LICENSE BLOCK ----- */
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    // nsISupports interface:
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   // nsIFrame:
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   // nsISVGValueObserver
00105   NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable);
00106   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable);
00107 
00108   // nsISupportsWeakReference
00109   // implementation inherited from nsSupportsWeakReference
00110 
00111   // nsISVGChildFrame interface:
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   // nsISVGContainerFrame interface:
00122   NS_IMETHOD_(nsISVGOuterSVGFrame*) GetOuterSVGFrame();
00123 
00124 protected:
00125 };
00126 
00127 //----------------------------------------------------------------------
00128 // Implementation
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 //  printf("nsSVGGenericContainerFrame CTOR\n");
00146 #endif
00147 }
00148 
00149 nsSVGGenericContainerFrame::~nsSVGGenericContainerFrame()
00150 {
00151 #ifdef DEBUG
00152 //  printf("~nsSVGGenericContainerFrame\n");
00153 #endif
00154 }
00155 
00156 nsresult nsSVGGenericContainerFrame::Init()
00157 {
00158   return NS_OK;
00159 }
00160 
00161 //----------------------------------------------------------------------
00162 // nsISupports methods
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 // nsIFrame methods
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   // append == insert at end:
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   // Insert the new frames
00216   mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
00217 
00218   // call InitialUpdate() on all new frames:
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 // nsISVGValueObserver methods:
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 // nsISVGChildFrame methods
00314 
00315 NS_IMETHODIMP
00316 nsSVGGenericContainerFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
00317 {
00318 #ifdef DEBUG
00319 //  printf("nsSVGGenericContainer(%p)::Paint\n", this);
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 //  printf("nsSVGGenericContainerFrame(%p)::GetFrameForPoint\n", this);
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         // return NS_OK; can't return. we need reverse order but only
00349         // have a singly linked list...
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 // nsISVGContainerFrame methods:
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 }

Generated on Wed Sep 10 22:25:23 2003 for Mozilla SVG Project Rendering Backend by doxygen1.3