Back to index

lightning-sunbird  0.9+nobinonly
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 Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * 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 of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or 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 MPL, 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 "nsSVGGenericContainerFrame.h"
00040 
00041 //----------------------------------------------------------------------
00042 // nsSVGGenericContainerFrame Implementation
00043 
00044 nsresult
00045 NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame)
00046 {
00047   nsSVGGenericContainerFrame* it = new (aPresShell) nsSVGGenericContainerFrame;
00048   if (nsnull == it)
00049     return NS_ERROR_OUT_OF_MEMORY;
00050 
00051   *aNewFrame = it;
00052 
00053   return NS_OK;
00054 }
00055 
00056 nsSVGGenericContainerFrame::nsSVGGenericContainerFrame()
00057 {
00058 #ifdef DEBUG
00059 //  printf("nsSVGGenericContainerFrame CTOR\n");
00060 #endif
00061 }
00062 
00063 nsSVGGenericContainerFrame::~nsSVGGenericContainerFrame()
00064 {
00065 #ifdef DEBUG
00066 //  printf("~nsSVGGenericContainerFrame\n");
00067 #endif
00068 }
00069 
00070 nsresult nsSVGGenericContainerFrame::Init()
00071 {
00072   return NS_OK;
00073 }
00074 
00075 //----------------------------------------------------------------------
00076 // nsISupports methods
00077 
00078 NS_INTERFACE_MAP_BEGIN(nsSVGGenericContainerFrame)
00079   NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
00080   NS_INTERFACE_MAP_ENTRY(nsISVGContainerFrame)
00081 NS_INTERFACE_MAP_END_INHERITING(nsSVGGenericContainerFrameBase)
00082 
00083 
00084 //----------------------------------------------------------------------
00085 // nsIFrame methods
00086 NS_IMETHODIMP
00087 nsSVGGenericContainerFrame::Init(nsPresContext*  aPresContext,
00088                   nsIContent*      aContent,
00089                   nsIFrame*        aParent,
00090                   nsStyleContext*  aContext,
00091                   nsIFrame*        aPrevInFlow)
00092 {
00093   nsresult rv;
00094   rv = nsSVGGenericContainerFrameBase::Init(aPresContext, aContent, aParent,
00095                              aContext, aPrevInFlow);
00096 
00097   Init();
00098   
00099   return rv;
00100 }
00101 
00102 
00103 NS_IMETHODIMP
00104 nsSVGGenericContainerFrame::AppendFrames(nsIAtom*        aListName,
00105                                          nsIFrame*       aFrameList)
00106 {
00107   // append == insert at end:
00108   return InsertFrames(aListName, mFrames.LastChild(), aFrameList);  
00109 }
00110 
00111 NS_IMETHODIMP
00112 nsSVGGenericContainerFrame::InsertFrames(nsIAtom*        aListName,
00113                                          nsIFrame*       aPrevFrame,
00114                                          nsIFrame*       aFrameList)
00115 {
00116   nsIFrame* lastNewFrame = nsnull;
00117   {
00118     nsFrameList tmpList(aFrameList);
00119     lastNewFrame = tmpList.LastChild();
00120   }
00121   
00122   // Insert the new frames
00123   mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
00124 
00125   // call InitialUpdate() on all new frames:
00126   nsIFrame* end = nsnull;
00127   if (lastNewFrame)
00128     end = lastNewFrame->GetNextSibling();
00129 
00130   for (nsIFrame*kid=aFrameList; kid != end; kid = kid->GetNextSibling()) {
00131     nsISVGChildFrame* SVGFrame=nsnull;
00132     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00133     if (SVGFrame) {
00134       SVGFrame->InitialUpdate(); 
00135     }
00136   }
00137   
00138   return NS_OK;
00139 }
00140 
00141 NS_IMETHODIMP
00142 nsSVGGenericContainerFrame::RemoveFrame(nsIAtom*        aListName,
00143                                         nsIFrame*       aOldFrame)
00144 {
00145   nsCOMPtr<nsISVGRendererRegion> dirty_region;
00146   
00147   nsISVGChildFrame* SVGFrame=nsnull;
00148   aOldFrame->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00149 
00150   if (SVGFrame)
00151     dirty_region = SVGFrame->GetCoveredRegion();
00152 
00153   PRBool result = mFrames.DestroyFrame(GetPresContext(), aOldFrame);
00154 
00155   nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00156   NS_ASSERTION(outerSVGFrame, "no outer svg frame");
00157   if (dirty_region && outerSVGFrame)
00158     outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
00159 
00160   NS_ASSERTION(result, "didn't find frame to delete");
00161   return result ? NS_OK : NS_ERROR_FAILURE;
00162 }
00163 
00164 NS_IMETHODIMP
00165 nsSVGGenericContainerFrame::ReplaceFrame(nsIAtom*        aListName,
00166                                          nsIFrame*       aOldFrame,
00167                                          nsIFrame*       aNewFrame)
00168 {
00169   NS_NOTYETIMPLEMENTED("nsSVGGenericContainerFrame::ReplaceFrame");
00170   return NS_ERROR_NOT_IMPLEMENTED;
00171 }
00172 
00173 NS_IMETHODIMP
00174 nsSVGGenericContainerFrame::AttributeChanged(nsIContent*     aChild,
00175                                              PRInt32         aNameSpaceID,
00176                                              nsIAtom*        aAttribute,
00177                                              PRInt32         aModType)
00178 {
00179 #ifdef DEBUG
00180     nsAutoString str;
00181     aAttribute->ToString(str);
00182     printf("** nsSVGGenericContainerFrame::AttributeChanged(%s)\n",
00183            NS_LossyConvertUCS2toASCII(str).get());
00184 #endif
00185 
00186   return NS_OK;
00187 }
00188 
00189 nsIAtom *
00190 nsSVGGenericContainerFrame::GetType() const
00191 {
00192   return nsLayoutAtoms::svgGenericContainerFrame;
00193 }
00194 
00195 PRBool
00196 nsSVGGenericContainerFrame::IsFrameOfType(PRUint32 aFlags) const
00197 {
00198   return !(aFlags & ~nsIFrame::eSVG);
00199 }
00200 
00201 //----------------------------------------------------------------------
00202 // nsISVGChildFrame methods
00203 
00204 NS_IMETHODIMP
00205 nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
00206 {
00207 #ifdef DEBUG
00208 //  printf("nsSVGGenericContainer(%p)::Paint\n", this);
00209 #endif
00210   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00211        kid = kid->GetNextSibling()) {
00212     nsISVGChildFrame* SVGFrame=nsnull;
00213     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00214     if (SVGFrame)
00215       SVGFrame->PaintSVG(canvas, dirtyRectTwips);
00216   }
00217 
00218   return NS_OK;
00219 }
00220 
00221 NS_IMETHODIMP
00222 nsSVGGenericContainerFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
00223 {
00224 #ifdef DEBUG
00225 //  printf("nsSVGGenericContainerFrame(%p)::GetFrameForPoint\n", this);
00226 #endif
00227   *hit = nsnull;
00228   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00229        kid = kid->GetNextSibling()) {
00230     nsISVGChildFrame* SVGFrame=nsnull;
00231     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00232     if (SVGFrame) {
00233       nsIFrame* temp=nsnull;
00234       nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
00235       if (NS_SUCCEEDED(rv) && temp) {
00236         *hit = temp;
00237         // return NS_OK; can't return. we need reverse order but only
00238         // have a singly linked list...
00239       }
00240     }
00241   }
00242   
00243   return *hit ? NS_OK : NS_ERROR_FAILURE;
00244 }
00245 
00246 NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
00247 nsSVGGenericContainerFrame::GetCoveredRegion()
00248 {
00249   nsISVGRendererRegion *accu_region=nsnull;
00250   
00251   nsIFrame* kid = mFrames.FirstChild();
00252   while (kid) {
00253     nsISVGChildFrame* SVGFrame=0;
00254     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00255     if (SVGFrame) {
00256       nsCOMPtr<nsISVGRendererRegion> dirty_region = SVGFrame->GetCoveredRegion();
00257       if (dirty_region) {
00258         if (accu_region) {
00259           nsCOMPtr<nsISVGRendererRegion> temp = dont_AddRef(accu_region);
00260           dirty_region->Combine(temp, &accu_region);
00261         }
00262         else {
00263           accu_region = dirty_region;
00264           NS_IF_ADDREF(accu_region);
00265         }
00266       }
00267     }
00268     kid = kid->GetNextSibling();
00269   }
00270   
00271   return accu_region;
00272 }
00273 
00274 NS_IMETHODIMP
00275 nsSVGGenericContainerFrame::InitialUpdate()
00276 {
00277   nsIFrame* kid = mFrames.FirstChild();
00278   while (kid) {
00279     nsISVGChildFrame* SVGFrame=0;
00280     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00281     if (SVGFrame) {
00282       SVGFrame->InitialUpdate();
00283     }
00284     kid = kid->GetNextSibling();
00285   }
00286   return NS_OK;
00287 }  
00288 
00289 NS_IMETHODIMP
00290 nsSVGGenericContainerFrame::NotifyCanvasTMChanged()
00291 {
00292   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00293        kid = kid->GetNextSibling()) {
00294     nsISVGChildFrame* SVGFrame=nsnull;
00295     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00296     if (SVGFrame) {
00297       SVGFrame->NotifyCanvasTMChanged();
00298     }
00299   }
00300   return NS_OK;
00301 }
00302 
00303 NS_IMETHODIMP
00304 nsSVGGenericContainerFrame::NotifyRedrawSuspended()
00305 {
00306   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00307        kid = kid->GetNextSibling()) {
00308     nsISVGChildFrame* SVGFrame=0;
00309     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00310     if (SVGFrame) {
00311       SVGFrame->NotifyRedrawSuspended();
00312     }
00313   }
00314   return NS_OK;
00315 }
00316 
00317 NS_IMETHODIMP
00318 nsSVGGenericContainerFrame::NotifyRedrawUnsuspended()
00319 {
00320   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00321        kid = kid->GetNextSibling()) {
00322     nsISVGChildFrame* SVGFrame=nsnull;
00323     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00324     if (SVGFrame) {
00325       SVGFrame->NotifyRedrawUnsuspended();
00326     }
00327   }
00328  return NS_OK;
00329 }
00330 
00331 NS_IMETHODIMP
00332 nsSVGGenericContainerFrame::GetBBox(nsIDOMSVGRect **_retval)
00333 {
00334   *_retval = nsnull;
00335   return NS_ERROR_FAILURE;
00336 }
00337 
00338 //----------------------------------------------------------------------
00339 // nsISVGContainerFrame methods:
00340 
00341 nsISVGOuterSVGFrame *
00342 nsSVGGenericContainerFrame::GetOuterSVGFrame()
00343 {
00344   NS_ASSERTION(mParent, "null parent");
00345   
00346   nsISVGContainerFrame *containerFrame;
00347   mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
00348   if (!containerFrame) {
00349     NS_ERROR("invalid container");
00350     return nsnull;
00351   }
00352 
00353   return containerFrame->GetOuterSVGFrame();  
00354 }
00355 
00356 already_AddRefed<nsIDOMSVGMatrix>
00357 nsSVGGenericContainerFrame::GetCanvasTM()
00358 {
00359   NS_ASSERTION(mParent, "null parent");
00360   
00361   nsISVGContainerFrame *containerFrame;
00362   mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
00363   if (!containerFrame) {
00364     NS_ERROR("invalid container");
00365     return nsnull;
00366   }
00367 
00368   return containerFrame->GetCanvasTM();  
00369 }
00370 
00371 already_AddRefed<nsSVGCoordCtxProvider>
00372 nsSVGGenericContainerFrame::GetCoordContextProvider()
00373 {
00374   NS_ASSERTION(mParent, "null parent");
00375   
00376   nsISVGContainerFrame *containerFrame;
00377   mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
00378   if (!containerFrame) {
00379     NS_ERROR("invalid container");
00380     return nsnull;
00381   }
00382 
00383   return containerFrame->GetCoordContextProvider();  
00384 }
00385