layout/generic/nsCanvasFrame.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:5b16801e2467
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /* rendering object that goes directly inside the document's scrollbars */
7
8 #include "nsCanvasFrame.h"
9 #include "nsContainerFrame.h"
10 #include "nsCSSRendering.h"
11 #include "nsPresContext.h"
12 #include "nsStyleContext.h"
13 #include "nsRenderingContext.h"
14 #include "nsGkAtoms.h"
15 #include "nsIPresShell.h"
16 #include "nsDisplayList.h"
17 #include "nsCSSFrameConstructor.h"
18 #include "nsFrameManager.h"
19 #include "gfxPlatform.h"
20
21 // for focus
22 #include "nsIScrollableFrame.h"
23 #ifdef DEBUG_CANVAS_FOCUS
24 #include "nsIDocShell.h"
25 #endif
26
27 //#define DEBUG_CANVAS_FOCUS
28
29 using namespace mozilla;
30 using namespace mozilla::layout;
31 using namespace mozilla::gfx;
32
33 nsIFrame*
34 NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
35 {
36 return new (aPresShell) nsCanvasFrame(aContext);
37 }
38
39 NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
40
41 NS_QUERYFRAME_HEAD(nsCanvasFrame)
42 NS_QUERYFRAME_ENTRY(nsCanvasFrame)
43 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
44
45 void
46 nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
47 {
48 nsIScrollableFrame* sf =
49 PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
50 if (sf) {
51 sf->RemoveScrollPositionListener(this);
52 }
53
54 nsContainerFrame::DestroyFrom(aDestructRoot);
55 }
56
57 void
58 nsCanvasFrame::ScrollPositionWillChange(nscoord aX, nscoord aY)
59 {
60 if (mDoPaintFocus) {
61 mDoPaintFocus = false;
62 PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
63 }
64 }
65
66 NS_IMETHODIMP
67 nsCanvasFrame::SetHasFocus(bool aHasFocus)
68 {
69 if (mDoPaintFocus != aHasFocus) {
70 mDoPaintFocus = aHasFocus;
71 PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
72
73 if (!mAddedScrollPositionListener) {
74 nsIScrollableFrame* sf =
75 PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
76 if (sf) {
77 sf->AddScrollPositionListener(this);
78 mAddedScrollPositionListener = true;
79 }
80 }
81 }
82 return NS_OK;
83 }
84
85 nsresult
86 nsCanvasFrame::SetInitialChildList(ChildListID aListID,
87 nsFrameList& aChildList)
88 {
89 NS_ASSERTION(aListID != kPrincipalList ||
90 aChildList.IsEmpty() || aChildList.OnlyChild(),
91 "Primary child list can have at most one frame in it");
92 return nsContainerFrame::SetInitialChildList(aListID, aChildList);
93 }
94
95 nsresult
96 nsCanvasFrame::AppendFrames(ChildListID aListID,
97 nsFrameList& aFrameList)
98 {
99 NS_ASSERTION(aListID == kPrincipalList ||
100 aListID == kAbsoluteList, "unexpected child list ID");
101 NS_PRECONDITION(aListID != kAbsoluteList ||
102 mFrames.IsEmpty(), "already have a child frame");
103 if (aListID != kPrincipalList) {
104 // We only support the Principal and Absolute child lists.
105 return NS_ERROR_INVALID_ARG;
106 }
107
108 if (!mFrames.IsEmpty()) {
109 // We only allow a single principal child frame.
110 return NS_ERROR_INVALID_ARG;
111 }
112
113 // Insert the new frames
114 NS_ASSERTION(aFrameList.FirstChild() == aFrameList.LastChild(),
115 "Only one principal child frame allowed");
116 #ifdef DEBUG
117 nsFrame::VerifyDirtyBitSet(aFrameList);
118 #endif
119 mFrames.AppendFrames(nullptr, aFrameList);
120
121 PresContext()->PresShell()->
122 FrameNeedsReflow(this, nsIPresShell::eTreeChange,
123 NS_FRAME_HAS_DIRTY_CHILDREN);
124
125 return NS_OK;
126 }
127
128 nsresult
129 nsCanvasFrame::InsertFrames(ChildListID aListID,
130 nsIFrame* aPrevFrame,
131 nsFrameList& aFrameList)
132 {
133 // Because we only support a single child frame inserting is the same
134 // as appending
135 NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
136 if (aPrevFrame)
137 return NS_ERROR_UNEXPECTED;
138
139 return AppendFrames(aListID, aFrameList);
140 }
141
142 nsresult
143 nsCanvasFrame::RemoveFrame(ChildListID aListID,
144 nsIFrame* aOldFrame)
145 {
146 NS_ASSERTION(aListID == kPrincipalList ||
147 aListID == kAbsoluteList, "unexpected child list ID");
148 if (aListID != kPrincipalList && aListID != kAbsoluteList) {
149 // We only support the Principal and Absolute child lists.
150 return NS_ERROR_INVALID_ARG;
151 }
152
153 if (aOldFrame != mFrames.FirstChild())
154 return NS_ERROR_FAILURE;
155
156 // Remove the frame and destroy it
157 mFrames.DestroyFrame(aOldFrame);
158
159 PresContext()->PresShell()->
160 FrameNeedsReflow(this, nsIPresShell::eTreeChange,
161 NS_FRAME_HAS_DIRTY_CHILDREN);
162 return NS_OK;
163 }
164
165 nsRect nsCanvasFrame::CanvasArea() const
166 {
167 // Not clear which overflow rect we want here, but it probably doesn't
168 // matter.
169 nsRect result(GetVisualOverflowRect());
170
171 nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
172 if (scrollableFrame) {
173 nsRect portRect = scrollableFrame->GetScrollPortRect();
174 result.UnionRect(result, nsRect(nsPoint(0, 0), portRect.Size()));
175 }
176 return result;
177 }
178
179 void
180 nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
181 nsRenderingContext* aCtx)
182 {
183 nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
184 nsPoint offset = ToReferenceFrame();
185 nsRect bgClipRect = frame->CanvasArea() + offset;
186 if (NS_GET_A(mColor) > 0) {
187 aCtx->SetColor(mColor);
188 aCtx->FillRect(bgClipRect);
189 }
190 }
191
192 static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
193 {
194 aDest->Translate(gfxPoint(aRect.x, aRect.y));
195 aDest->SetSource(aSource);
196 aDest->NewPath();
197 aDest->Rectangle(gfxRect(0, 0, aRect.width, aRect.height));
198 aDest->Fill();
199 aDest->Translate(-gfxPoint(aRect.x, aRect.y));
200 }
201
202 static void BlitSurface(DrawTarget* aDest, const gfxRect& aRect, DrawTarget* aSource)
203 {
204 RefPtr<SourceSurface> source = aSource->Snapshot();
205 aDest->DrawSurface(source,
206 Rect(aRect.x, aRect.y, aRect.width, aRect.height),
207 Rect(0, 0, aRect.width, aRect.height));
208 }
209
210 void
211 nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
212 nsRenderingContext* aCtx)
213 {
214 nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
215 nsPoint offset = ToReferenceFrame();
216 nsRect bgClipRect = frame->CanvasArea() + offset;
217
218 nsRefPtr<nsRenderingContext> context;
219 nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
220 nsRefPtr<gfxASurface> surf;
221 RefPtr<DrawTarget> dt;
222 nsRefPtr<gfxContext> ctx;
223 gfxRect destRect;
224 #ifndef MOZ_GFX_OPTIMIZE_MOBILE
225 if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
226 aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
227 !dest->CurrentMatrix().HasNonIntegerTranslation()) {
228 // Snap image rectangle to nearest pixel boundaries. This is the right way
229 // to snap for this context, because we checked HasNonIntegerTranslation above.
230 destRect.Round();
231 if (dest->IsCairo()) {
232 surf = static_cast<gfxASurface*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
233 nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
234 if (surf && surf->GetType() == destSurf->GetType()) {
235 BlitSurface(dest, destRect, surf);
236 return;
237 }
238 surf = destSurf->CreateSimilarSurface(
239 gfxContentType::COLOR_ALPHA,
240 gfxIntSize(ceil(destRect.width), ceil(destRect.height)));
241 } else {
242 dt = static_cast<DrawTarget*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImageDT()));
243 DrawTarget* destDT = dest->GetDrawTarget();
244 if (dt) {
245 BlitSurface(destDT, destRect, dt);
246 return;
247 }
248 dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width), ceil(destRect.height)), SurfaceFormat::B8G8R8A8);
249 }
250 if (surf || dt) {
251 if (surf) {
252 ctx = new gfxContext(surf);
253 } else {
254 ctx = new gfxContext(dt);
255 }
256 ctx->Translate(-gfxPoint(destRect.x, destRect.y));
257 context = new nsRenderingContext();
258 context->Init(aCtx->DeviceContext(), ctx);
259 }
260 }
261 #endif
262
263 PaintInternal(aBuilder,
264 (surf || dt) ? context.get() : aCtx,
265 (surf || dt) ? bgClipRect: mVisibleRect,
266 &bgClipRect);
267
268 if (surf) {
269 BlitSurface(dest, destRect, surf);
270 frame->Properties().Set(nsIFrame::CachedBackgroundImage(),
271 surf.forget().take());
272 }
273 if (dt) {
274 BlitSurface(dest->GetDrawTarget(), destRect, dt);
275 frame->Properties().Set(nsIFrame::CachedBackgroundImageDT(), dt.forget().drop());
276 }
277 }
278
279 void
280 nsDisplayCanvasThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
281 nsRenderingContext* aCtx)
282 {
283 nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
284 nsPoint offset = ToReferenceFrame();
285 nsRect bgClipRect = frame->CanvasArea() + offset;
286
287 PaintInternal(aBuilder, aCtx, mVisibleRect, &bgClipRect);
288 }
289
290 /**
291 * A display item to paint the focus ring for the document.
292 *
293 * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
294 */
295 class nsDisplayCanvasFocus : public nsDisplayItem {
296 public:
297 nsDisplayCanvasFocus(nsDisplayListBuilder* aBuilder, nsCanvasFrame *aFrame)
298 : nsDisplayItem(aBuilder, aFrame)
299 {
300 MOZ_COUNT_CTOR(nsDisplayCanvasFocus);
301 }
302 virtual ~nsDisplayCanvasFocus() {
303 MOZ_COUNT_DTOR(nsDisplayCanvasFocus);
304 }
305
306 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
307 bool* aSnap) MOZ_OVERRIDE
308 {
309 *aSnap = false;
310 // This is an overestimate, but that's not a problem.
311 nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
312 return frame->CanvasArea() + ToReferenceFrame();
313 }
314
315 virtual void Paint(nsDisplayListBuilder* aBuilder,
316 nsRenderingContext* aCtx) MOZ_OVERRIDE
317 {
318 nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
319 frame->PaintFocus(*aCtx, ToReferenceFrame());
320 }
321
322 NS_DISPLAY_DECL_NAME("CanvasFocus", TYPE_CANVAS_FOCUS)
323 };
324
325 void
326 nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
327 const nsRect& aDirtyRect,
328 const nsDisplayListSet& aLists)
329 {
330 if (GetPrevInFlow()) {
331 DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
332 }
333
334 // Force a background to be shown. We may have a background propagated to us,
335 // in which case StyleBackground wouldn't have the right background
336 // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
337 // a background.
338 // We don't have any border or outline, and our background draws over
339 // the overflow area, so just add nsDisplayCanvasBackground instead of
340 // calling DisplayBorderBackgroundOutline.
341 if (IsVisibleForPainting(aBuilder)) {
342 nsStyleContext* bgSC;
343 const nsStyleBackground* bg = nullptr;
344 bool isThemed = IsThemed();
345 if (!isThemed && nsCSSRendering::FindBackground(this, &bgSC)) {
346 bg = bgSC->StyleBackground();
347 }
348 aLists.BorderBackground()->AppendNewToTop(
349 new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this));
350
351 if (isThemed) {
352 aLists.BorderBackground()->AppendNewToTop(
353 new (aBuilder) nsDisplayCanvasThemedBackground(aBuilder, this));
354 return;
355 }
356
357 if (!bg) {
358 return;
359 }
360
361 // Create separate items for each background layer.
362 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
363 if (bg->mLayers[i].mImage.IsEmpty()) {
364 continue;
365 }
366 aLists.BorderBackground()->AppendNewToTop(
367 new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, i, bg));
368 }
369 }
370
371 nsIFrame* kid;
372 for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
373 // Put our child into its own pseudo-stack.
374 BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
375 }
376
377 #ifdef DEBUG_CANVAS_FOCUS
378 nsCOMPtr<nsIContent> focusContent;
379 aPresContext->EventStateManager()->
380 GetFocusedContent(getter_AddRefs(focusContent));
381
382 bool hasFocus = false;
383 nsCOMPtr<nsISupports> container;
384 aPresContext->GetContainer(getter_AddRefs(container));
385 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
386 if (docShell) {
387 docShell->GetHasFocus(&hasFocus);
388 printf("%p - nsCanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
389 mRect.x, mRect.y, mRect.width, mRect.height,
390 aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
391 }
392 printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
393 focusContent.get(), mDoPaintFocus?"Y":"N");
394 #endif
395
396 if (!mDoPaintFocus)
397 return;
398 // Only paint the focus if we're visible
399 if (!StyleVisibility()->IsVisible())
400 return;
401
402 aLists.Outlines()->AppendNewToTop(new (aBuilder)
403 nsDisplayCanvasFocus(aBuilder, this));
404 }
405
406 void
407 nsCanvasFrame::PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt)
408 {
409 nsRect focusRect(aPt, GetSize());
410
411 nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
412 if (scrollableFrame) {
413 nsRect portRect = scrollableFrame->GetScrollPortRect();
414 focusRect.width = portRect.width;
415 focusRect.height = portRect.height;
416 focusRect.MoveBy(scrollableFrame->GetScrollPosition());
417 }
418
419 // XXX use the root frame foreground color, but should we find BODY frame
420 // for HTML documents?
421 nsIFrame* root = mFrames.FirstChild();
422 const nsStyleColor* color = root ? root->StyleColor() : StyleColor();
423 if (!color) {
424 NS_ERROR("current color cannot be found");
425 return;
426 }
427
428 nsCSSRendering::PaintFocus(PresContext(), aRenderingContext,
429 focusRect, color->mColor);
430 }
431
432 /* virtual */ nscoord
433 nsCanvasFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
434 {
435 nscoord result;
436 DISPLAY_MIN_WIDTH(this, result);
437 if (mFrames.IsEmpty())
438 result = 0;
439 else
440 result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
441 return result;
442 }
443
444 /* virtual */ nscoord
445 nsCanvasFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
446 {
447 nscoord result;
448 DISPLAY_PREF_WIDTH(this, result);
449 if (mFrames.IsEmpty())
450 result = 0;
451 else
452 result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
453 return result;
454 }
455
456 nsresult
457 nsCanvasFrame::Reflow(nsPresContext* aPresContext,
458 nsHTMLReflowMetrics& aDesiredSize,
459 const nsHTMLReflowState& aReflowState,
460 nsReflowStatus& aStatus)
461 {
462 DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame");
463 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
464 NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow");
465
466 // Initialize OUT parameter
467 aStatus = NS_FRAME_COMPLETE;
468
469 nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*>
470 (GetPrevInFlow());
471 if (prevCanvasFrame) {
472 AutoFrameListPtr overflow(aPresContext,
473 prevCanvasFrame->StealOverflowFrames());
474 if (overflow) {
475 NS_ASSERTION(overflow->OnlyChild(),
476 "must have doc root as canvas frame's only child");
477 nsContainerFrame::ReparentFrameViewList(*overflow, prevCanvasFrame, this);
478 // Prepend overflow to the our child list. There may already be
479 // children placeholders for fixed-pos elements, which don't get
480 // reflowed but must not be lost until the canvas frame is destroyed.
481 mFrames.InsertFrames(this, nullptr, *overflow);
482 }
483 }
484
485 // Set our size up front, since some parts of reflow depend on it
486 // being already set. Note that the computed height may be
487 // unconstrained; that's ok. Consumers should watch out for that.
488 SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight()));
489
490 // Reflow our one and only normal child frame. It's either the root
491 // element's frame or a placeholder for that frame, if the root element
492 // is abs-pos or fixed-pos. We may have additional children which
493 // are placeholders for continuations of fixed-pos content, but those
494 // don't need to be reflowed. The normal child is always comes before
495 // the fixed-pos placeholders, because we insert it at the start
496 // of the child list, above.
497 nsHTMLReflowMetrics kidDesiredSize(aReflowState);
498 if (mFrames.IsEmpty()) {
499 // We have no child frame, so return an empty size
500 aDesiredSize.Width() = aDesiredSize.Height() = 0;
501 } else {
502 nsIFrame* kidFrame = mFrames.FirstChild();
503 bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
504
505 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
506 nsSize(aReflowState.AvailableWidth(),
507 aReflowState.AvailableHeight()));
508
509 if (aReflowState.mFlags.mVResize &&
510 (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
511 // Tell our kid it's being vertically resized too. Bit of a
512 // hack for framesets.
513 kidReflowState.mFlags.mVResize = true;
514 }
515
516 nsPoint kidPt(kidReflowState.ComputedPhysicalMargin().left,
517 kidReflowState.ComputedPhysicalMargin().top);
518
519 kidReflowState.ApplyRelativePositioning(&kidPt);
520
521 // Reflow the frame
522 ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
523 kidPt.x, kidPt.y, 0, aStatus);
524
525 // Complete the reflow and position and size the child frame
526 FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState,
527 kidPt.x, kidPt.y, 0);
528
529 if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
530 nsIFrame* nextFrame = kidFrame->GetNextInFlow();
531 NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
532 "If it's incomplete and has no nif yet, it must flag a nif reflow.");
533 if (!nextFrame) {
534 nextFrame = aPresContext->PresShell()->FrameConstructor()->
535 CreateContinuingFrame(aPresContext, kidFrame, this);
536 SetOverflowFrames(nsFrameList(nextFrame, nextFrame));
537 // Root overflow containers will be normal children of
538 // the canvas frame, but that's ok because there
539 // aren't any other frames we need to isolate them from
540 // during reflow.
541 }
542 if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
543 nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
544 }
545 }
546
547 // If the child frame was just inserted, then we're responsible for making sure
548 // it repaints
549 if (kidDirty) {
550 // But we have a new child, which will affect our background, so
551 // invalidate our whole rect.
552 // Note: Even though we request to be sized to our child's size, our
553 // scroll frame ensures that we are always the size of the viewport.
554 // Also note: GetPosition() on a CanvasFrame is always going to return
555 // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect()
556 // could also include overflow to our top and left (out of the viewport)
557 // which doesn't need to be painted.
558 nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
559 viewport->InvalidateFrame();
560 }
561
562 // Return our desired size. Normally it's what we're told, but
563 // sometimes we can be given an unconstrained height (when a window
564 // is sizing-to-content), and we should compute our desired height.
565 aDesiredSize.Width() = aReflowState.ComputedWidth();
566 if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
567 aDesiredSize.Height() = kidFrame->GetRect().height +
568 kidReflowState.ComputedPhysicalMargin().TopBottom();
569 } else {
570 aDesiredSize.Height() = aReflowState.ComputedHeight();
571 }
572
573 aDesiredSize.SetOverflowAreasToDesiredBounds();
574 aDesiredSize.mOverflowAreas.UnionWith(
575 kidDesiredSize.mOverflowAreas + kidPt);
576 }
577
578 if (prevCanvasFrame) {
579 ReflowOverflowContainerChildren(aPresContext, aReflowState,
580 aDesiredSize.mOverflowAreas, 0,
581 aStatus);
582 }
583
584 FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
585
586 NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
587 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
588 return NS_OK;
589 }
590
591 nsIAtom*
592 nsCanvasFrame::GetType() const
593 {
594 return nsGkAtoms::canvasFrame;
595 }
596
597 nsresult
598 nsCanvasFrame::GetContentForEvent(WidgetEvent* aEvent,
599 nsIContent** aContent)
600 {
601 NS_ENSURE_ARG_POINTER(aContent);
602 nsresult rv = nsFrame::GetContentForEvent(aEvent,
603 aContent);
604 if (NS_FAILED(rv) || !*aContent) {
605 nsIFrame* kid = mFrames.FirstChild();
606 if (kid) {
607 rv = kid->GetContentForEvent(aEvent,
608 aContent);
609 }
610 }
611
612 return rv;
613 }
614
615 #ifdef DEBUG_FRAME_DUMP
616 nsresult
617 nsCanvasFrame::GetFrameName(nsAString& aResult) const
618 {
619 return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult);
620 }
621 #endif

mercurial