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
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
00071
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
00083 NS_DECL_ISUPPORTS
00084
00085
00086 NS_DECL_NSISVGRECTANGLESINK
00087 private:
00088 nsCOMPtr<nsIViewManager> mViewManager;
00089 nsIView* mView;
00090 int mTwipsPerPx;
00091 };
00092
00093
00094
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
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
00124
00125
00126 NS_IMETHODIMP
00127 VMRectInvalidator::SinkRectangle(float x, float y, float width, float height)
00128 {
00129 #ifdef DEBUG
00130
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
00141
00142
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
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
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
00219 NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable);
00220 NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable);
00221
00222
00223
00224
00225
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
00235 NS_IMETHOD_(nsISVGOuterSVGFrame*) GetOuterSVGFrame();
00236
00237 protected:
00238
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
00254 nsIPresShell* mPresShell;
00255 PRUint32 mRedrawSuspendCount;
00256 PRBool mNeedsReflow;
00257 PRBool mViewportInitialized;
00258 nsCOMPtr<nsISVGRenderer> mRenderer;
00259 };
00260
00261
00262
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
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
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
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
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
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
00375
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
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 nsSize availSpace(0, 0);
00393 nsHTMLReflowState state(aPresContext, aReflowState, *iter, availSpace);
00394 (*iter)->Reflow (aPresContext,
00395 aDesiredSize,
00396 state,
00397 aStatus);
00398
00399
00400
00401
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
00410 aStatus = NS_FRAME_COMPLETE;
00411 return NS_OK;
00412 }
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 #ifdef DEBUG
00429
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
00441
00442
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
00452
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
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 #endif
00494
00495
00496
00497
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
00532
00533 aStatus = NS_FRAME_COMPLETE;
00534 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00535
00536
00537
00538
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
00570 mViewportInitialized = PR_TRUE;
00571
00572
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
00591
00592 NS_IMETHODIMP
00593 nsSVGOuterSVGFrame::AppendFrames(nsIPresContext* aPresContext,
00594 nsIPresShell& aPresShell,
00595 nsIAtom* aListName,
00596 nsIFrame* aFrameList)
00597 {
00598
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
00611 nsIFrame* lastNewFrame = nsnull;
00612 {
00613 nsFrameList tmpList(aFrameList);
00614 lastNewFrame = tmpList.LastChild();
00615 }
00616
00617
00618 mFrames.InsertFrames(this, aPrevFrame, aFrameList);
00619
00620 SuspendRedraw();
00621
00622
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
00688
00689
00690
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
00704
00705
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
00731
00732 }
00733 }
00734 }
00735
00736 return NS_OK;
00737 }
00738
00739
00740
00741
00742
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
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
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
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
00812 nsRect dirtyRectPx((int)(aDirtyRect.x*pxPerTwips), (int)(aDirtyRect.y*pxPerTwips),
00813 (int)(aDirtyRect.width*pxPerTwips), (int)(aDirtyRect.height*pxPerTwips));
00814
00815
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
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
00845
00846 }
00847
00848
00849
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
00872
00873 NS_IMETHODIMP
00874 nsSVGOuterSVGFrame::InvalidateRegion(nsISVGRendererRegion* region, PRBool bRedraw)
00875 {
00876
00877
00878
00879 if (!region && !bRedraw) return NS_OK;
00880
00881 NS_ENSURE_TRUE(mPresShell, NS_ERROR_FAILURE);
00882
00883
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
00911 #endif
00912 if (++mRedrawSuspendCount != 1)
00913 return NS_OK;
00914
00915
00916
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
00937 #endif
00938 if (--mRedrawSuspendCount > 0)
00939 return NS_OK;
00940
00941 NS_ASSERTION(mRedrawSuspendCount >=0, "unbalanced suspend count!");
00942
00943
00944
00945 if (mNeedsReflow)
00946 InitiateReflow();
00947
00948
00949
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
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
01000 if (!mViewportInitialized) return NS_OK;
01001
01002
01003
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
01019
01020 NS_IMETHODIMP_(nsISVGOuterSVGFrame *)
01021 nsSVGOuterSVGFrame::GetOuterSVGFrame()
01022 {
01023 return this;
01024 }
01025
01026
01027
01028
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
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 }