/layout/svg/base/src/nsSVGOuterSVGFrame.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 "nsHTMLContainerFrame.h"
00040 #include "nsContainerFrame.h"
00041 #include "nsCSSRendering.h"
00042 #include "nsISVGSVGElement.h"
00043 #include "nsIPresContext.h"
00044 #include "nsIDOMSVGAnimatedLength.h"
00045 #include "nsIDOMSVGLength.h"
00046 #include "nsISVGContainerFrame.h"
00047 #include "nsISVGChildFrame.h"
00048 #include "nsISVGOuterSVGFrame.h"
00049 #include "nsISVGRendererCanvas.h"
00050 #include "nsIView.h"
00051 #include "nsIViewManager.h"
00052 #include "nsWeakReference.h"
00053 #include "nsISVGValue.h"
00054 #include "nsISVGValueObserver.h"
00055 #include "nsHTMLParts.h"
00056 #include "nsReflowPath.h"
00057 #include "nsISVGRenderer.h"
00058 #include "nsISVGRendererRegion.h"
00059 #include "nsIServiceManager.h"
00060 #include "nsISVGRectangleSink.h"
00061 #include "nsISVGValueUtils.h"
00062 #include "nsISVGViewportRect.h"
00063 #include "nsISVGViewportAxis.h"
00064 #include "nsIDOMSVGNumber.h"
00065 #if defined(DEBUG) && defined(SVG_DEBUG_PRINTING)
00066 #include "nsIDeviceContext.h"
00067 #include "nsTransform2D.h"
00068 #endif
00069 
00070 // VMRectInvalidator: helper class for invalidating rects on the viewmanager.
00071 // used in nsSVGOuterSVGFrame::InvalidateRegion
00072 
00073 class VMRectInvalidator : public nsISVGRectangleSink
00074 {  
00075 protected:
00076   friend already_AddRefed<nsISVGRectangleSink> CreateVMRectInvalidator(nsIViewManager* vm,
00077                                                                        nsIView* view,
00078                                                                        int twipsPerPx);
00079   VMRectInvalidator(nsIViewManager* vm, nsIView* view, int twipsPerPx); 
00080 
00081 public:
00082   // nsISupports interface:
00083   NS_DECL_ISUPPORTS
00084 
00085   // nsISVGRectangleSink interface:
00086   NS_DECL_NSISVGRECTANGLESINK
00087 private:
00088   nsCOMPtr<nsIViewManager> mViewManager;
00089   nsIView* mView;
00090   int mTwipsPerPx;
00091 };
00092 
00093 //----------------------------------------------------------------------
00094 // Implementation:
00095 
00096 VMRectInvalidator::VMRectInvalidator(nsIViewManager* vm, nsIView* view,
00097                                      int twipsPerPx)
00098     : mViewManager(vm), mView(view), mTwipsPerPx(twipsPerPx)
00099 {
00100 }
00101 
00102 already_AddRefed<nsISVGRectangleSink>
00103 CreateVMRectInvalidator(nsIViewManager* vm, nsIView* view, int twipsPerPx)
00104 {
00105   nsISVGRectangleSink* retval = new VMRectInvalidator(vm, view, twipsPerPx);
00106   NS_IF_ADDREF(retval);
00107   return retval;
00108 }
00109 
00110 
00111 //----------------------------------------------------------------------
00112 // nsISupports methods:
00113 
00114 NS_IMPL_ADDREF(VMRectInvalidator)
00115 NS_IMPL_RELEASE(VMRectInvalidator)
00116 
00117 NS_INTERFACE_MAP_BEGIN(VMRectInvalidator)
00118   NS_INTERFACE_MAP_ENTRY(nsISVGRectangleSink)
00119   NS_INTERFACE_MAP_ENTRY(nsISupports)
00120 NS_INTERFACE_MAP_END
00121 
00122 //----------------------------------------------------------------------
00123 // nsISVGRectangleSink methods:
00124 
00125 /* void sinkRectangle (in float x, in float y, in float width, in float height); */
00126 NS_IMETHODIMP
00127 VMRectInvalidator::SinkRectangle(float x, float y, float width, float height)
00128 {
00129 #ifdef DEBUG
00130   // printf("invalidating %f %f %f %f\n", x,y,width,height);
00131 #endif
00132   nsRect rect((nscoord)(x*mTwipsPerPx), (nscoord)(y*mTwipsPerPx),
00133               (nscoord)(width*mTwipsPerPx), (nscoord)(height*mTwipsPerPx));
00134   mViewManager->UpdateView(mView, rect, NS_VMREFRESH_NO_SYNC);
00135   return NS_OK;
00136 }
00137 
00138 
00140 // nsSVGOuterSVGFrame class
00141 
00142 //typedef nsHTMLContainerFrame nsSVGOuterSVGFrameBase;
00143 typedef nsContainerFrame nsSVGOuterSVGFrameBase;
00144 
00145 class nsSVGOuterSVGFrame : public nsSVGOuterSVGFrameBase,
00146                            public nsISVGOuterSVGFrame,
00147                            public nsISVGContainerFrame,
00148                            public nsISVGValueObserver,
00149                            public nsSupportsWeakReference
00150 {
00151   friend nsresult
00152   NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00153 protected:
00154   nsSVGOuterSVGFrame();
00155   virtual ~nsSVGOuterSVGFrame();
00156   nsresult Init();
00157   
00158    // nsISupports interface:
00159   NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
00160 private:
00161   NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
00162   NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }  
00163 public:
00164   // nsIFrame:
00165   NS_IMETHOD Init(nsIPresContext*  aPresContext,
00166                   nsIContent*      aContent,
00167                   nsIFrame*        aParent,
00168                   nsStyleContext*  aContext,
00169                   nsIFrame*        aPrevInFlow);
00170   
00171   NS_IMETHOD Reflow(nsIPresContext*          aPresContext,
00172                     nsHTMLReflowMetrics&     aDesiredSize,
00173                     const nsHTMLReflowState& aReflowState,
00174                     nsReflowStatus&          aStatus);
00175 
00176   NS_IMETHOD  DidReflow(nsIPresContext*   aPresContext,
00177                         const nsHTMLReflowState*  aReflowState,
00178                         nsDidReflowStatus aStatus);
00179 
00180 
00181   NS_IMETHOD  AppendFrames(nsIPresContext* aPresContext,
00182                            nsIPresShell&   aPresShell,
00183                            nsIAtom*        aListName,
00184                            nsIFrame*       aFrameList);
00185   NS_IMETHOD  InsertFrames(nsIPresContext* aPresContext,
00186                            nsIPresShell&   aPresShell,
00187                            nsIAtom*        aListName,
00188                            nsIFrame*       aPrevFrame,
00189                            nsIFrame*       aFrameList);
00190   NS_IMETHOD  RemoveFrame(nsIPresContext* aPresContext,
00191                           nsIPresShell&   aPresShell,
00192                           nsIAtom*        aListName,
00193                           nsIFrame*       aOldFrame);
00194   NS_IMETHOD  ReplaceFrame(nsIPresContext* aPresContext,
00195                            nsIPresShell&   aPresShell,
00196                            nsIAtom*        aListName,
00197                            nsIFrame*       aOldFrame,
00198                            nsIFrame*       aNewFrame);
00199 
00200   NS_IMETHOD  AttributeChanged(nsIPresContext* aPresContext,
00201                                nsIContent*     aChild,
00202                                PRInt32         aNameSpaceID,
00203                                nsIAtom*        aAttribute,
00204                                PRInt32         aModType);
00205 
00206   NS_IMETHOD  GetFrameForPoint(nsIPresContext* aPresContext,
00207                                const nsPoint& aPoint, 
00208                                nsFramePaintLayer aWhichLayer,
00209                                nsIFrame**     aFrame);
00210 
00211   
00212   NS_IMETHOD  Paint(nsIPresContext* aPresContext,
00213                     nsIRenderingContext& aRenderingContext,
00214                     const nsRect& aDirtyRect,
00215                     nsFramePaintLayer aWhichLayer,
00216                     PRUint32 aFlags = 0);
00217 
00218   // nsISVGValueObserver
00219   NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable);
00220   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable);
00221 
00222   // nsISupportsWeakReference
00223   // implementation inherited from nsSupportsWeakReference
00224   
00225   // nsISVGOuterSVGFrame interface:
00226   NS_IMETHOD InvalidateRegion(nsISVGRendererRegion* region, PRBool bRedraw);
00227   NS_IMETHOD IsRedrawSuspended(PRBool* isSuspended);
00228   NS_IMETHOD SuspendRedraw();
00229   NS_IMETHOD UnsuspendRedraw();
00230   NS_IMETHOD GetRenderer(nsISVGRenderer**renderer);
00231   NS_IMETHOD CreateSVGRect(nsIDOMSVGRect **_retval);
00232   NS_IMETHOD NotifyViewportChange();
00233 
00234   // nsISVGContainerFrame interface:
00235   NS_IMETHOD_(nsISVGOuterSVGFrame*) GetOuterSVGFrame();
00236   
00237 protected:
00238   // implementation helpers:
00239   void InitiateReflow();
00240   
00241   float GetPxPerTwips();
00242   float GetTwipsPerPx();
00243 
00244   void AddAsWidthHeightObserver();
00245   void RemoveAsWidthHeightObserver();
00246 
00247   void CalculateAvailableSpace(nsRect *maxRect, nsRect *preferredRect,
00248                                nsIPresContext* aPresContext,
00249                                const nsHTMLReflowState& aReflowState);
00250   nsresult SetViewportDimensions(nsISVGViewportRect* vp, float width, float height);
00251   nsresult SetViewportScale(nsISVGViewportRect* vp, nsIPresContext *context);
00252   
00253 //  nsIView* mView;
00254   nsIPresShell* mPresShell; // XXX is a non-owning ref ok?
00255   PRUint32 mRedrawSuspendCount;
00256   PRBool mNeedsReflow;
00257   PRBool mViewportInitialized;
00258   nsCOMPtr<nsISVGRenderer> mRenderer;
00259 };
00260 
00261 //----------------------------------------------------------------------
00262 // Implementation
00263 
00264 nsresult
00265 NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame)
00266 {
00267   *aNewFrame = nsnull;
00268   
00269   nsCOMPtr<nsIDOMSVGSVGElement> svgElement = do_QueryInterface(aContent);
00270   if (!svgElement) {
00271 #ifdef DEBUG
00272     printf("warning: trying to construct an SVGOuterSVGFrame for a content element that doesn't support the right interfaces\n");
00273 #endif
00274     return NS_ERROR_FAILURE;
00275   }
00276 
00277   nsSVGOuterSVGFrame* it = new (aPresShell) nsSVGOuterSVGFrame;
00278   if (nsnull == it)
00279     return NS_ERROR_OUT_OF_MEMORY;
00280 
00281   *aNewFrame = it;
00282 
00283   // XXX is this ok?
00284   it->mPresShell = aPresShell;
00285   
00286   return NS_OK;
00287 }
00288 
00289 nsSVGOuterSVGFrame::nsSVGOuterSVGFrame()
00290     : mRedrawSuspendCount(0),
00291       mNeedsReflow(PR_FALSE),
00292       mViewportInitialized(PR_FALSE)
00293 {
00294 }
00295 
00296 nsSVGOuterSVGFrame::~nsSVGOuterSVGFrame()
00297 {
00298 #ifdef DEBUG
00299 //  printf("~nsSVGOuterSVGFrame %p\n", this);
00300 #endif
00301   RemoveAsWidthHeightObserver();
00302 }
00303 
00304 nsresult nsSVGOuterSVGFrame::Init()
00305 {
00306 #if defined(MOZ_SVG_RENDERER_GDIPLUS) && defined(MOZ_SVG_RENDERER_LIBART)
00307 #error "Multiple SVG renderers. Please choose one manually."
00308 #elif defined(MOZ_SVG_RENDERER_GDIPLUS)  
00309   mRenderer = do_CreateInstance(NS_SVG_RENDERER_GDIPLUS_CONTRACTID);
00310 #elif defined(MOZ_SVG_RENDERER_LIBART)
00311   mRenderer = do_CreateInstance(NS_SVG_RENDERER_LIBART_CONTRACTID);
00312 #else
00313 #error "No SVG renderer."
00314 #endif
00315   NS_ASSERTION(mRenderer, "could not get renderer");
00316   AddAsWidthHeightObserver();
00317   SuspendRedraw();
00318   return NS_OK;
00319 }
00320 
00321 //----------------------------------------------------------------------
00322 // nsISupports methods
00323 
00324 NS_INTERFACE_MAP_BEGIN(nsSVGOuterSVGFrame)
00325   NS_INTERFACE_MAP_ENTRY(nsISVGContainerFrame)
00326   NS_INTERFACE_MAP_ENTRY(nsISVGOuterSVGFrame)
00327   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
00328   NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
00329 NS_INTERFACE_MAP_END_INHERITING(nsSVGOuterSVGFrameBase)
00330 
00331 //----------------------------------------------------------------------
00332 // nsIFrame methods
00333 
00334 NS_IMETHODIMP
00335 nsSVGOuterSVGFrame::Init(nsIPresContext*  aPresContext,
00336                   nsIContent*      aContent,
00337                   nsIFrame*        aParent,
00338                   nsStyleContext*  aContext,
00339                   nsIFrame*        aPrevInFlow)
00340 {
00341   nsresult rv;
00342   rv = nsSVGOuterSVGFrameBase::Init(aPresContext, aContent, aParent,
00343                                     aContext, aPrevInFlow);
00344 
00345   Init();
00346 
00347   return rv;
00348 }
00349 
00350 
00351   
00352 //----------------------------------------------------------------------
00353 // reflowing
00354 
00355 NS_IMETHODIMP
00356 nsSVGOuterSVGFrame::Reflow(nsIPresContext*          aPresContext,
00357                            nsHTMLReflowMetrics&     aDesiredSize,
00358                            const nsHTMLReflowState& aReflowState,
00359                            nsReflowStatus&          aStatus)
00360 {
00361   nsresult rv;
00362   
00363 #if defined(DEBUG) && defined(SVG_DEBUG_PRINTING)
00364   {
00365     printf("nsSVGOuterSVGFrame(%p)::Reflow()[\n",this);
00366     float twipsPerScPx,twipsPerPx;
00367     aPresContext->GetScaledPixelsToTwips(&twipsPerScPx);
00368     aPresContext->GetPixelsToTwips(&twipsPerPx);
00369     printf("tw/sc(px)=%f tw/px=%f\n", twipsPerScPx, twipsPerPx);
00370     printf("]\n");
00371   }
00372 #endif
00373   
00374   // check whether this reflow request is targeted at us or a child
00375   // frame (e.g. a foreignObject):
00376   if (aReflowState.reason == eReflowReason_Incremental) {
00377     nsReflowPath::iterator iter = aReflowState.path->FirstChild();
00378     nsReflowPath::iterator end = aReflowState.path->EndChildren();
00379 
00380     for ( ; iter != end; ++iter) {
00381       // The actual target of this reflow is one of our child
00382       // frames. Since SVG as such doesn't use reflow, this will
00383       // probably be the child of a <foreignObject>. Some HTML|XUL
00384       // content frames target reflow events at themselves when they
00385       // need to be redrawn in response to e.g. a style change. For
00386       // correct visual updating, we must make sure the reflow
00387       // reaches its intended target.
00388         
00389       // Since it is an svg frame (probably an nsSVGForeignObjectFrame),
00390       // we might as well pass in our aDesiredSize and aReflowState
00391       // objects - they are ignored by svg frames:
00392       nsSize availSpace(0, 0); // XXXwaterson probably wrong!
00393       nsHTMLReflowState state(aPresContext, aReflowState, *iter, availSpace);
00394       (*iter)->Reflow (aPresContext,
00395                        aDesiredSize,
00396                        state,
00397                        aStatus);
00398 
00399       // XXX do we really have to return our metrics although we're
00400       // not affected by the reflow? Is there a way of telling our
00401       // parent that we don't want anything changed?
00402       aDesiredSize.width  = mRect.width;
00403       aDesiredSize.height = mRect.height;
00404       aDesiredSize.ascent = aDesiredSize.height;
00405       aDesiredSize.descent = 0;
00406     }
00407 
00408     if (! aReflowState.path->mReflowCommand) {
00409       // We're not the target of the incremental reflow, so just bail.
00410       aStatus = NS_FRAME_COMPLETE;
00411       return NS_OK;
00412     }
00413   }
00414   
00415   //  SVG CR 20001102: When the SVG content is embedded inline within
00416   //  a containing document, and that document is styled using CSS,
00417   //  then if there are CSS positioning properties specified on the
00418   //  outermost 'svg' element that are sufficient to establish the
00419   //  width of the viewport, then these positioning properties
00420   //  establish the viewport's width; otherwise, the width attribute
00421   //  on the outermost 'svg' element establishes the viewport's width.
00422   //  Similarly, if there are CSS positioning properties specified on
00423   //  the outermost 'svg' element that are sufficient to establish the
00424   //  height of the viewport, then these positioning properties
00425   //  establish the viewport's height; otherwise, the height attribute
00426   //  on the outermost 'svg' element establishes the viewport's
00427   //  height.
00428 #ifdef DEBUG
00429   // printf("--- nsSVGOuterSVGFrame(%p)::Reflow(frame:%p,reason:%d) ---\n",this,aReflowState.frame,aReflowState.reason);
00430 #endif
00431   
00432   NS_ENSURE_TRUE(mContent, NS_ERROR_FAILURE);
00433 
00434   nsCOMPtr<nsISVGSVGElement> SVGElement = do_QueryInterface(mContent);
00435   NS_ENSURE_TRUE(SVGElement, NS_ERROR_FAILURE);
00436 
00437   float pxPerTwips = GetPxPerTwips();
00438   float twipsPerPx = GetTwipsPerPx();
00439 
00440   // The width/height attribs given on the <svg>-element might be
00441   // percentage values of the parent viewport. We will set the parent
00442   // viewport dimensions to the available space.
00443 
00444   nsRect maxRect, preferredRect;
00445   CalculateAvailableSpace(&maxRect, &preferredRect, aPresContext, aReflowState);
00446   float preferredWidth = preferredRect.width * pxPerTwips;
00447   float preferredHeight = preferredRect.height * pxPerTwips;
00448 
00449   SuspendRedraw(); 
00450   
00451   // As soon as we set the viewport, the width/height attributes might
00452   // emit change-notifications. We don't want those right now:
00453   RemoveAsWidthHeightObserver();
00454 
00455   nsCOMPtr<nsISVGViewportRect> parentViewport;
00456   SVGElement->GetParentViewportRect(getter_AddRefs(parentViewport));
00457   NS_ENSURE_TRUE(parentViewport, NS_ERROR_FAILURE);
00458 
00459   nsCOMPtr<nsISVGValue> pvp_value = do_QueryInterface(parentViewport);
00460   pvp_value->BeginBatchUpdate();
00461   rv = SetViewportDimensions(parentViewport, preferredWidth, preferredHeight);
00462   NS_ENSURE_SUCCESS(rv,rv);
00463   rv = SetViewportScale(parentViewport, aPresContext);
00464   NS_ENSURE_SUCCESS(rv,rv);
00465   pvp_value->EndBatchUpdate();
00466   
00467 #ifdef DEBUG
00468   // some debug stuff:
00469 //   {
00470 //     nsRect r;
00471 //     aPresContext->GetVisibleArea(r);
00472 //     printf("******* aw: %d, ah: %d visiw: %d, visih: %d\n",
00473 //            aReflowState.availableWidth,
00474 //            aReflowState.availableHeight,
00475 //            r.width, r.height);
00476 //     printf("******* cw: %d, ch: %d \n    cmaxw: %d, cmaxh: %d\n",
00477 //            aReflowState.mComputedWidth,
00478 //            aReflowState.mComputedHeight,
00479 //            aReflowState.mComputedMaxWidth,
00480 //            aReflowState.mComputedMaxHeight);
00481 
00482 //     if (aReflowState.parentReflowState) {
00483 //       printf("******* parent aw: %d, parent ah: %d \n",
00484 //              aReflowState.parentReflowState->availableWidth,
00485 //              aReflowState.parentReflowState->availableHeight);
00486 //       printf("******* parent cw: %d, parent ch: %d \n  parent cmaxw: %d, parent cmaxh: %d\n",
00487 //              aReflowState.parentReflowState->mComputedWidth,
00488 //              aReflowState.parentReflowState->mComputedHeight,
00489 //              aReflowState.parentReflowState->mComputedMaxWidth,
00490 //              aReflowState.parentReflowState->mComputedMaxHeight);
00491 //     }
00492 //   }
00493 #endif
00494 
00495   // now that the parent viewport dimensions have been set, the
00496   // width/height attributes will be valid.
00497   // Let's work out our desired dimensions.
00498 
00499   float width;
00500   {
00501     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
00502     SVGElement->GetWidth(getter_AddRefs(animLength));
00503     NS_ENSURE_TRUE(animLength, NS_ERROR_FAILURE);
00504     nsCOMPtr<nsIDOMSVGLength> length;
00505     animLength->GetAnimVal(getter_AddRefs(length));
00506     NS_ENSURE_TRUE(length, NS_ERROR_FAILURE);
00507     
00508     length->GetValue(&width);
00509     
00510     aDesiredSize.width = (int)(width*twipsPerPx);
00511   }
00512 
00513   float height;
00514   {
00515     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
00516     SVGElement->GetHeight(getter_AddRefs(animLength));
00517     NS_ENSURE_TRUE(animLength, NS_ERROR_FAILURE);
00518     nsCOMPtr<nsIDOMSVGLength> length;
00519     animLength->GetAnimVal(getter_AddRefs(length));
00520     NS_ENSURE_TRUE(length, NS_ERROR_FAILURE);
00521     
00522     length->GetValue(&height);
00523     
00524     aDesiredSize.height = (int)(height*twipsPerPx);
00525   }
00526   
00527 
00528   aDesiredSize.ascent = aDesiredSize.height;
00529   aDesiredSize.descent = 0;
00530   
00531   // XXX add in CSS borders ??
00532 
00533   aStatus = NS_FRAME_COMPLETE;
00534   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00535 
00536   // Set the viewport.
00537   // XXX. I have a feeling that this code belongs in DidReflow(),
00538   // using mRect. Bug #118723 prevents us from putting it there.
00539   nsCOMPtr<nsIDOMSVGRect> domViewport;
00540   SVGElement->GetViewport(getter_AddRefs(domViewport));
00541   NS_ENSURE_TRUE(domViewport, NS_ERROR_FAILURE);
00542   nsCOMPtr<nsISVGViewportRect> viewport = do_QueryInterface(domViewport);
00543   NS_ENSURE_TRUE(viewport, NS_ERROR_FAILURE);  
00544 
00545   nsCOMPtr<nsISVGValue> vp_value = do_QueryInterface(viewport);
00546   vp_value->BeginBatchUpdate();
00547   rv = SetViewportDimensions(viewport, width, height);
00548   NS_ENSURE_SUCCESS(rv,rv);
00549   rv = SetViewportScale(viewport, aPresContext);
00550   NS_ENSURE_SUCCESS(rv,rv);
00551   vp_value->EndBatchUpdate();
00552   
00553   AddAsWidthHeightObserver();
00554   
00555   UnsuspendRedraw();
00556 
00557   
00558   return NS_OK;
00559 }
00560 
00561 NS_IMETHODIMP
00562 nsSVGOuterSVGFrame::DidReflow(nsIPresContext*   aPresContext,
00563                               const nsHTMLReflowState*  aReflowState,
00564                               nsDidReflowStatus aStatus)
00565 {
00566   nsresult rv = nsSVGOuterSVGFrameBase::DidReflow(aPresContext,aReflowState,aStatus);
00567 
00568   if (!mViewportInitialized) {
00569     // it is now
00570     mViewportInitialized = PR_TRUE;
00571 
00572     // call InitialUpdate() on all frames:
00573     nsIFrame* kid = mFrames.FirstChild();
00574     while (kid) {
00575       nsISVGChildFrame* SVGFrame=nsnull;
00576       kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00577       if (SVGFrame) {
00578         SVGFrame->InitialUpdate(); 
00579       }
00580       kid->GetNextSibling(&kid);
00581     }
00582     
00583     UnsuspendRedraw();
00584   }
00585   
00586   return rv;
00587 }
00588 
00589 //----------------------------------------------------------------------
00590 // container methods
00591 
00592 NS_IMETHODIMP
00593 nsSVGOuterSVGFrame::AppendFrames(nsIPresContext* aPresContext,
00594                       nsIPresShell&   aPresShell,
00595                       nsIAtom*        aListName,
00596                       nsIFrame*       aFrameList)
00597 {
00598   // append == insert at end:
00599   return InsertFrames(aPresContext, aPresShell, aListName,
00600                       mFrames.LastChild(), aFrameList);  
00601 }
00602 
00603 NS_IMETHODIMP
00604 nsSVGOuterSVGFrame::InsertFrames(nsIPresContext* aPresContext,
00605                       nsIPresShell&   aPresShell,
00606                       nsIAtom*        aListName,
00607                       nsIFrame*       aPrevFrame,
00608                       nsIFrame*       aFrameList)
00609 {
00610   // memorize last new frame
00611   nsIFrame* lastNewFrame = nsnull;
00612   {
00613     nsFrameList tmpList(aFrameList);
00614     lastNewFrame = tmpList.LastChild();
00615   }
00616   
00617   // Insert the new frames
00618   mFrames.InsertFrames(this, aPrevFrame, aFrameList);
00619 
00620   SuspendRedraw();
00621 
00622   // call InitialUpdate() on all new frames:
00623   
00624   nsIFrame* end = nsnull;
00625   if (lastNewFrame)
00626     lastNewFrame->GetNextSibling(&end);
00627 
00628   for (nsIFrame* kid = aFrameList; kid != end;
00629        kid = kid->GetNextSibling()) {
00630     nsISVGChildFrame* SVGFrame=nsnull;
00631     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00632     if (SVGFrame) {
00633       SVGFrame->InitialUpdate(); 
00634     }
00635   }
00636 
00637   UnsuspendRedraw();
00638   
00639   return NS_OK;
00640 }
00641 
00642 NS_IMETHODIMP
00643 nsSVGOuterSVGFrame::RemoveFrame(nsIPresContext* aPresContext,
00644                      nsIPresShell&   aPresShell,
00645                      nsIAtom*        aListName,
00646                      nsIFrame*       aOldFrame)
00647 {
00648   nsCOMPtr<nsISVGRendererRegion> dirty_region;
00649   
00650   nsISVGChildFrame* SVGFrame=nsnull;
00651   aOldFrame->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00652 
00653   if (SVGFrame)
00654     dirty_region = SVGFrame->GetCoveredRegion();
00655 
00656   PRBool result = mFrames.DestroyFrame(aPresContext, aOldFrame);
00657 
00658   nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00659   NS_ASSERTION(outerSVGFrame, "no outer svg frame");
00660   if (dirty_region && outerSVGFrame)
00661     outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
00662 
00663   NS_ASSERTION(result, "didn't find frame to delete");
00664   return result ? NS_OK : NS_ERROR_FAILURE;
00665 }
00666 
00667 NS_IMETHODIMP
00668 nsSVGOuterSVGFrame::ReplaceFrame(nsIPresContext* aPresContext,
00669                       nsIPresShell&   aPresShell,
00670                       nsIAtom*        aListName,
00671                       nsIFrame*       aOldFrame,
00672                       nsIFrame*       aNewFrame)
00673 {
00674   NS_NOTYETIMPLEMENTED("write me!");
00675   return NS_ERROR_UNEXPECTED;
00676 }
00677 
00678 NS_IMETHODIMP
00679 nsSVGOuterSVGFrame::AttributeChanged(nsIPresContext* aPresContext,
00680                                      nsIContent*     aChild,
00681                                      PRInt32         aNameSpaceID,
00682                                      nsIAtom*        aAttribute,
00683                                      PRInt32         aModType)
00684 {
00685 #ifdef DEBUG
00686 //  {
00687 //    nsAutoString str;
00688 //    aAttribute->ToString(str);
00689 //    printf("** nsSVGOuterSVGFrame::AttributeChanged(%s)\n",
00690 //           NS_LossyConvertUCS2toASCII(str).get());
00691 //  }
00692 #endif
00693   return NS_OK;
00694 }
00695 
00696 
00697 nsresult
00698 nsSVGOuterSVGFrame::GetFrameForPoint(nsIPresContext* aPresContext,
00699                                      const nsPoint& aPoint,
00700                                      nsFramePaintLayer aWhichLayer,
00701                                      nsIFrame**     aFrame)
00702 {
00703   // XXX This algorithm is really bad. Because we only have a
00704   // singly-linked list we have to test each and every SVG element for
00705   // a hit. What we really want is a double-linked list.
00706   
00707 
00708   *aFrame = nsnull;
00709   if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND) return NS_ERROR_FAILURE;
00710   
00711   float x = GetPxPerTwips() * ( aPoint.x - mRect.x);
00712   float y = GetPxPerTwips() * ( aPoint.y - mRect.y);
00713   
00714   PRBool inThisFrame = mRect.Contains(aPoint);
00715   
00716   if (!inThisFrame) {
00717     return NS_ERROR_FAILURE;
00718   }
00719 
00720   *aFrame = this;
00721   nsIFrame* hit = nsnull;
00722   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00723        kid = kid->GetNextSibling()) {
00724     nsISVGChildFrame* SVGFrame=nsnull;
00725     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00726     if (SVGFrame) {
00727       nsresult rv = SVGFrame->GetFrameForPoint(x, y, &hit);
00728       if (NS_SUCCEEDED(rv) && hit) {
00729         *aFrame = hit;
00730         // return NS_OK; can't return. we need reverse order but only
00731         // have a singly linked list...
00732       }
00733     }
00734   }
00735     
00736   return NS_OK;
00737 }
00738 
00739 
00740 
00741 //----------------------------------------------------------------------
00742 // painting
00743 
00744 NS_IMETHODIMP
00745 nsSVGOuterSVGFrame::Paint(nsIPresContext* aPresContext,
00746                           nsIRenderingContext& aRenderingContext,
00747                           const nsRect& aDirtyRect,
00748                           nsFramePaintLayer aWhichLayer,
00749                           PRUint32 aFlags)
00750 {
00751   
00752 //    if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
00753 //      if (GetStyleDisplay()->IsVisible() && mRect.width && mRect.height) {
00754 //        // Paint our background and border
00755 //        const nsStyleBorder* border = GetStyleBorder();
00756 //        const nsStylePadding* padding = GetStylePadding();
00757 //        const nsStyleOutline* outline = GetStyleOutline();
00758 
00759 //        nsRect  rect(0, 0, mRect.width, mRect.height);
00760 // //       nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
00761 // //                                       aDirtyRect, rect, *border, *padding, PR_TRUE);
00762 //        nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00763 //                                    aDirtyRect, rect, *border, mStyleContext, 0);
00764 //        nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
00765 //                                    aDirtyRect, rect, *border, *outline, mStyleContext, 0);
00766       
00767 //      }
00768 //    }
00769 
00770   if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND) return NS_OK;
00771   if (aDirtyRect.width<=0 || aDirtyRect.height<=0) return NS_OK;
00772 
00773 #if defined(DEBUG) && defined(SVG_DEBUG_PRINTING)
00774   {
00775     nsCOMPtr<nsIDeviceContext>  dx;
00776     aRenderingContext.GetDeviceContext(*getter_AddRefs(dx));
00777     float zoom,tzoom,scale;
00778     dx->GetZoom(zoom);
00779     dx->GetTextZoom(tzoom);
00780     dx->GetCanonicalPixelScale(scale);
00781     printf("nsSVGOuterSVGFrame(%p)::Paint()[ z=%f tz=%f ps=%f\n",this,zoom,tzoom,scale);
00782     printf("dirtyrect= %d, %d, %d, %d\n", aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
00783     nsTransform2D* xform;
00784     aRenderingContext.GetCurrentTransform(xform);
00785     printf("translation=(%f,%f)\n", xform->GetXTranslation(), xform->GetYTranslation());
00786     float sx=1.0f,sy=1.0f;
00787     xform->TransformNoXLate(&sx,&sy);
00788     printf("scale=(%f,%f)\n", sx, sy);
00789     float twipsPerScPx,twipsPerPx;
00790     aPresContext->GetScaledPixelsToTwips(&twipsPerScPx);
00791     aPresContext->GetPixelsToTwips(&twipsPerPx);
00792     printf("tw/sc(px)=%f tw/px=%f\n", twipsPerScPx, twipsPerPx);
00793     int fontsc;
00794     aPresContext->GetFontScaler(&fontsc);
00795     printf("font scale=%d\n",fontsc);
00796     printf("]\n");
00797   }
00798 #endif
00799   
00800   // initialize Mozilla rendering context
00801   aRenderingContext.PushState();
00802   
00803   PRBool clipState;
00804   aRenderingContext.SetClipRect(aDirtyRect,nsClipCombine_kIntersect,clipState);
00805 
00806 #if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
00807   PRTime start = PR_Now();
00808 #endif
00809 
00810   float pxPerTwips = GetPxPerTwips();
00811   // XXX why do we need to inflate the rect here? 
00812   nsRect dirtyRectPx((int)(aDirtyRect.x*pxPerTwips), (int)(aDirtyRect.y*pxPerTwips),
00813                      (int)(aDirtyRect.width*pxPerTwips), (int)(aDirtyRect.height*pxPerTwips));
00814 //   nsRect dirtyRectPx((int)(aDirtyRect.x*pxPerTwips-1), (int)(aDirtyRect.y*pxPerTwips-1),
00815 //                      (int)(aDirtyRect.width*pxPerTwips+2), (int)(aDirtyRect.height*pxPerTwips+2));
00816   
00817   nsCOMPtr<nsISVGRendererCanvas> canvas;
00818   mRenderer->CreateCanvas(&aRenderingContext, aPresContext, dirtyRectPx,
00819                           getter_AddRefs(canvas));
00820 
00821   canvas->Clear(NS_RGB(255,255,255));
00822 
00823   // paint children:
00824   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00825        kid = kid->GetNextSibling()) {
00826     nsISVGChildFrame* SVGFrame=nsnull;
00827     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00828     if (SVGFrame)
00829       SVGFrame->Paint(canvas, aDirtyRect);
00830   }
00831   
00832   canvas->Flush();
00833 
00834   canvas = nsnull;
00835 
00836 #if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
00837   PRTime end = PR_Now();
00838   printf("SVG Paint Timing: %f ms\n", (end-start)/1000.0);
00839 #endif
00840   
00841   aRenderingContext.PopState(clipState);
00842   
00843   return NS_OK;
00844   // see if we have to draw a selection frame around this container
00845   //return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00846 }
00847 
00848 //----------------------------------------------------------------------
00849 // nsISVGValueObserver methods:
00850 
00851 NS_IMETHODIMP
00852 nsSVGOuterSVGFrame::WillModifySVGObservable(nsISVGValue* observable)
00853 {
00854   return NS_OK;
00855 }
00856 
00857 
00858 NS_IMETHODIMP
00859 nsSVGOuterSVGFrame::DidModifySVGObservable(nsISVGValue* observable)
00860 {
00861   mNeedsReflow = PR_TRUE;
00862   if (mRedrawSuspendCount==0) {
00863     InitiateReflow();
00864   }
00865   
00866   return NS_OK;
00867 }
00868 
00869 
00870 //----------------------------------------------------------------------
00871 // nsISVGOuterSVGFrame methods:
00872 
00873 NS_IMETHODIMP
00874 nsSVGOuterSVGFrame::InvalidateRegion(nsISVGRendererRegion* region, PRBool bRedraw)
00875 {
00876 //  NS_ASSERTION(mView, "need a view!");
00877 //  if (!mView) return NS_ERROR_FAILURE;
00878   
00879   if (!region && !bRedraw) return NS_OK;
00880 
00881   NS_ENSURE_TRUE(mPresShell, NS_ERROR_FAILURE);
00882 
00883   // just ignore invalidates if painting is suppressed by the shell
00884   PRBool suppressed = PR_FALSE;
00885   mPresShell->IsPaintingSuppressed(&suppressed);
00886   if (suppressed) return NS_OK;
00887   
00888   nsIView* view = GetClosestView();
00889   NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
00890 
00891   nsIViewManager* vm = view->GetViewManager();
00892 
00893   vm->BeginUpdateViewBatch();
00894   if (region) {
00895     nsCOMPtr<nsISVGRectangleSink> sink = CreateVMRectInvalidator(vm, view,
00896                                                                  (int)(GetTwipsPerPx()+0.5f));
00897     NS_ASSERTION(sink, "could not create rectangle sink for viewmanager");
00898     if (sink)
00899       region->GetRectangleScans(sink);
00900   }
00901   vm->EndUpdateViewBatch(bRedraw ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC);
00902   
00903   return NS_OK;
00904 }
00905 
00906 NS_IMETHODIMP
00907 nsSVGOuterSVGFrame::SuspendRedraw()
00908 {
00909 #ifdef DEBUG
00910   //printf("suspend redraw (count=%d)\n", mRedrawSuspendCount);
00911 #endif
00912   if (++mRedrawSuspendCount != 1)
00913     return NS_OK;
00914 
00915  // get the view manager, so that we can wrap this up in a batch
00916   // update.
00917   nsIViewManager* vm = GetPresContext()->GetViewManager();
00918 
00919   vm->BeginUpdateViewBatch();
00920  
00921   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00922        kid = kid->GetNextSibling()) {
00923     nsISVGChildFrame* SVGFrame=nsnull;
00924     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00925     if (SVGFrame) {
00926       SVGFrame->NotifyRedrawSuspended();
00927     }
00928   }
00929   return NS_OK;
00930 }
00931 
00932 NS_IMETHODIMP
00933 nsSVGOuterSVGFrame::UnsuspendRedraw()
00934 {
00935 #ifdef DEBUG
00936 //  printf("unsuspend redraw (count=%d)\n", mRedrawSuspendCount);
00937 #endif
00938   if (--mRedrawSuspendCount > 0)
00939     return NS_OK;
00940   
00941   NS_ASSERTION(mRedrawSuspendCount >=0, "unbalanced suspend count!");
00942   
00943   // If we need to reflow, do so before we update any of our
00944   // children. Reflows are likely to affect the display of children:
00945   if (mNeedsReflow)
00946     InitiateReflow();
00947   
00948   // get the view manager, so that we can wrap this up in a batch
00949   // update.
00950   nsIViewManager* vm = GetPresContext()->GetViewManager();
00951   
00952   for (nsIFrame* kid = mFrames.FirstChild(); kid;
00953        kid = kid->GetNextSibling()) {
00954     nsISVGChildFrame* SVGFrame=nsnull;
00955     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
00956     if (SVGFrame) {
00957       SVGFrame->NotifyRedrawUnsuspended();
00958     }
00959   }
00960 
00961   NS_ENSURE_TRUE(mPresShell, NS_ERROR_FAILURE);
00962 
00963   // don't do an immediate refresh if painting is suppressed by the shell
00964   PRBool suppressed = PR_FALSE;
00965   mPresShell->IsPaintingSuppressed(&suppressed);
00966   vm->EndUpdateViewBatch(suppressed ?
00967                          NS_VMREFRESH_NO_SYNC : NS_VMREFRESH_IMMEDIATE);
00968   return NS_OK;
00969 }
00970 
00971 NS_IMETHODIMP
00972 nsSVGOuterSVGFrame::IsRedrawSuspended(PRBool* isSuspended)
00973 {
00974   *isSuspended = (mRedrawSuspendCount>0) || !mViewportInitialized;
00975   return NS_OK;
00976 }
00977 
00978 NS_IMETHODIMP
00979 nsSVGOuterSVGFrame::GetRenderer(nsISVGRenderer**renderer)
00980 {
00981   *renderer = mRenderer;
00982   NS_IF_ADDREF(*renderer);
00983   return NS_OK;
00984 }
00985 
00986 NS_IMETHODIMP
00987 nsSVGOuterSVGFrame::CreateSVGRect(nsIDOMSVGRect **_retval)
00988 {
00989   nsCOMPtr<nsIDOMSVGSVGElement> svgElement = do_QueryInterface(mContent);
00990   NS_ASSERTION(svgElement, "wrong content element");  
00991   if(svgElement)
00992     return svgElement->CreateSVGRect(_retval);
00993   return NS_ERROR_FAILURE;
00994 }
00995 
00996 NS_IMETHODIMP
00997 nsSVGOuterSVGFrame::NotifyViewportChange()
00998 {
00999   // no point in doing anything when were not init'ed yet:
01000   if (!mViewportInitialized) return NS_OK;
01001 
01002   // inform children
01003   // XXX we should have an nsISVGChildFrame:NotifyViewportChange() function
01004   SuspendRedraw();
01005   nsIFrame* kid = mFrames.FirstChild();
01006   while (kid) {
01007     nsISVGChildFrame* SVGFrame=nsnull;
01008     kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
01009     if (SVGFrame)
01010       SVGFrame->NotifyCTMChanged(); 
01011     kid->GetNextSibling(&kid);
01012   }
01013   UnsuspendRedraw();
01014   return NS_OK;
01015 }
01016 
01017 //----------------------------------------------------------------------
01018 // nsISVGContainerFrame methods:
01019 
01020 NS_IMETHODIMP_(nsISVGOuterSVGFrame *)
01021 nsSVGOuterSVGFrame::GetOuterSVGFrame()
01022 {
01023   return this;
01024 }
01025 
01026 
01027 //----------------------------------------------------------------------
01028 // Implementation helpers
01029 
01030 float nsSVGOuterSVGFrame::GetPxPerTwips()
01031 {
01032   float val = GetTwipsPerPx();
01033   
01034   NS_ASSERTION(val!=0.0f, "invalid px/twips");  
01035   if (val == 0.0) val = 1e-20f;
01036   
01037   return 1.0f/val;
01038 }
01039 
01040 float nsSVGOuterSVGFrame::GetTwipsPerPx()
01041 {
01042   float twipsPerPx;
01043   GetPresContext()->GetScaledPixelsToTwips(&twipsPerPx);
01044   return twipsPerPx;
01045 }
01046 
01047 void nsSVGOuterSVGFrame::InitiateReflow()
01048 {
01049   mNeedsReflow = PR_FALSE;
01050   
01051   // Generate a reflow command to reflow ourselves
01052   nsHTMLReflowCommand *reflowCmd;
01053   NS_NewHTMLReflowCommand(&reflowCmd, this, eReflowType_ReflowDirty);
01054   if (!reflowCmd) {
01055     NS_ERROR("error creating reflow command object");
01056     return;
01057   }
01058   
01059   mPresShell->AppendReflowCommand(reflowCmd);
01060   mPresShell->FlushPendingNotifications(PR_FALSE);  
01061 }
01062 
01063 
01064 void nsSVGOuterSVGFrame::AddAsWidthHeightObserver()
01065 {
01066   nsCOMPtr<nsIDOMSVGSVGElement> svgElement = do_QueryInterface(mContent);
01067   NS_ASSERTION(svgElement, "wrong content element");  
01068  
01069   {
01070     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
01071     svgElement->GetWidth(getter_AddRefs(animLength));
01072     NS_ASSERTION(animLength, "could not get <svg>:width");
01073     nsCOMPtr<nsIDOMSVGLength> length;
01074     animLength->GetAnimVal(getter_AddRefs(length));
01075     NS_ASSERTION(length, "could not get <svg>:width:animval");
01076     NS_ADD_SVGVALUE_OBSERVER(length);
01077   }
01078 
01079   {
01080     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
01081     svgElement->GetHeight(getter_AddRefs(animLength));
01082     NS_ASSERTION(animLength, "could not get <svg>:height");
01083     nsCOMPtr<nsIDOMSVGLength> length;
01084     animLength->GetAnimVal(getter_AddRefs(length));
01085     NS_ASSERTION(length, "could not get <svg>:height:animval");
01086     NS_ADD_SVGVALUE_OBSERVER(length);
01087   }  
01088 }
01089 
01090 void nsSVGOuterSVGFrame::RemoveAsWidthHeightObserver()
01091 {
01092   nsCOMPtr<nsIDOMSVGSVGElement> svgElement = do_QueryInterface(mContent);
01093   NS_ASSERTION(svgElement, "wrong content element");  
01094 
01095   {
01096     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
01097     svgElement->GetWidth(getter_AddRefs(animLength));
01098     NS_ASSERTION(animLength, "could not get <svg>:width");
01099     nsCOMPtr<nsIDOMSVGLength> length;
01100     animLength->GetAnimVal(getter_AddRefs(length));
01101     NS_ASSERTION(length, "could not get <svg>:width:animval");
01102     NS_REMOVE_SVGVALUE_OBSERVER(length);
01103   }
01104 
01105   {
01106     nsCOMPtr<nsIDOMSVGAnimatedLength> animLength;
01107     svgElement->GetHeight(getter_AddRefs(animLength));
01108     NS_ASSERTION(animLength, "could not get <svg>:height");
01109     nsCOMPtr<nsIDOMSVGLength> length;
01110     animLength->GetAnimVal(getter_AddRefs(length));
01111     NS_ASSERTION(length, "could not get <svg>:height:animval");
01112     NS_REMOVE_SVGVALUE_OBSERVER(length);
01113   }  
01114 }
01115 
01116 void
01117 nsSVGOuterSVGFrame::CalculateAvailableSpace(nsRect *maxRect,
01118                                             nsRect *preferredRect,
01119                                             nsIPresContext* aPresContext,
01120                                             const nsHTMLReflowState& aReflowState)
01121 {
01122   aPresContext->GetVisibleArea(*preferredRect);
01123   
01124   if (aReflowState.availableWidth != NS_INTRINSICSIZE)
01125     maxRect->width = aReflowState.availableWidth;
01126   else if (aReflowState.parentReflowState &&
01127            aReflowState.parentReflowState->mComputedWidth != NS_INTRINSICSIZE)
01128     maxRect->width = aReflowState.parentReflowState->mComputedWidth;
01129   else
01130     maxRect->width = NS_MAXSIZE;
01131   
01132   if (aReflowState.availableHeight != NS_INTRINSICSIZE)
01133     maxRect->height = aReflowState.availableHeight;    
01134   else if (aReflowState.parentReflowState &&
01135            aReflowState.parentReflowState->mComputedHeight != NS_INTRINSICSIZE)
01136     maxRect->height = aReflowState.parentReflowState->mComputedHeight;
01137   else
01138     maxRect->height = NS_MAXSIZE;
01139 
01140   if (preferredRect->width > maxRect->width)
01141     preferredRect->width = maxRect->width;
01142   if (preferredRect->height > maxRect->height)
01143     preferredRect->height = maxRect->height;
01144 }  
01145 
01146 
01147 nsresult
01148 nsSVGOuterSVGFrame::SetViewportDimensions(nsISVGViewportRect* vp,
01149                                           float width, float height)
01150 {
01151   {
01152     nsCOMPtr<nsISVGViewportAxis> axis;
01153     vp->GetXAxis(getter_AddRefs(axis));
01154     NS_ENSURE_TRUE(axis, NS_ERROR_FAILURE);
01155     nsCOMPtr<nsIDOMSVGNumber> length;
01156     axis->GetLength(getter_AddRefs(length));
01157     length->SetValue(width);
01158   }
01159 
01160   {
01161     nsCOMPtr<nsISVGViewportAxis> axis;
01162     vp->GetYAxis(getter_AddRefs(axis));
01163     NS_ENSURE_TRUE(axis, NS_ERROR_FAILURE);
01164     nsCOMPtr<nsIDOMSVGNumber> length;
01165     axis->GetLength(getter_AddRefs(length));
01166     length->SetValue(height);
01167   }
01168   return NS_OK;
01169 }  
01170 
01171 nsresult
01172 nsSVGOuterSVGFrame::SetViewportScale(nsISVGViewportRect* vp, nsIPresContext *context)
01173 {
01174   float TwipsPerPx;
01175   context->GetScaledPixelsToTwips(&TwipsPerPx);
01176   float mmPerPx = TwipsPerPx / TWIPS_PER_POINT_FLOAT / (72.0f * 0.03937f);
01177 
01178   nsCOMPtr<nsIDOMSVGNumber> scaleX;
01179   {
01180     nsCOMPtr<nsISVGViewportAxis> axis;
01181     vp->GetXAxis(getter_AddRefs(axis));
01182     NS_ENSURE_TRUE(axis, NS_ERROR_FAILURE);
01183     axis->GetMillimeterPerPixel(getter_AddRefs(scaleX));
01184   }
01185 
01186   nsCOMPtr<nsIDOMSVGNumber> scaleY;
01187   {
01188     nsCOMPtr<nsISVGViewportAxis> axis;
01189     vp->GetYAxis(getter_AddRefs(axis));
01190     NS_ENSURE_TRUE(axis, NS_ERROR_FAILURE);
01191     axis->GetMillimeterPerPixel(getter_AddRefs(scaleY));
01192   }
01193 
01194   float old_x, old_y;
01195 
01196   scaleX->GetValue(&old_x);
01197   scaleY->GetValue(&old_y);
01198 
01199   if (old_x != mmPerPx || old_y != mmPerPx) {
01200     scaleX->SetValue(mmPerPx);
01201     scaleY->SetValue(mmPerPx);
01202   }
01203   
01204   return NS_OK;
01205 }

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