1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Pierre Phaneuf <pp@ludusdesign.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /* base class of all rendering objects */
40 :
41 : #ifndef nsFrame_h___
42 : #define nsFrame_h___
43 :
44 : #include "nsBox.h"
45 : #include "nsRect.h"
46 : #include "nsString.h"
47 : #include "prlog.h"
48 :
49 : #include "nsIPresShell.h"
50 : #include "nsFrameSelection.h"
51 : #include "nsHTMLReflowState.h"
52 : #include "nsHTMLReflowMetrics.h"
53 : #include "nsHTMLParts.h"
54 :
55 : /**
56 : * nsFrame logging constants. We redefine the nspr
57 : * PRLogModuleInfo.level field to be a bitfield. Each bit controls a
58 : * specific type of logging. Each logging operation has associated
59 : * inline methods defined below.
60 : */
61 : #define NS_FRAME_TRACE_CALLS 0x1
62 : #define NS_FRAME_TRACE_PUSH_PULL 0x2
63 : #define NS_FRAME_TRACE_CHILD_REFLOW 0x4
64 : #define NS_FRAME_TRACE_NEW_FRAMES 0x8
65 :
66 : #define NS_FRAME_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
67 :
68 : #ifdef NS_DEBUG
69 : #define NS_FRAME_LOG(_bit,_args) \
70 : PR_BEGIN_MACRO \
71 : if (NS_FRAME_LOG_TEST(nsFrame::GetLogModuleInfo(),_bit)) { \
72 : PR_LogPrint _args; \
73 : } \
74 : PR_END_MACRO
75 : #else
76 : #define NS_FRAME_LOG(_bit,_args)
77 : #endif
78 :
79 : // XXX Need to rework this so that logging is free when it's off
80 : #ifdef NS_DEBUG
81 : #define NS_FRAME_TRACE_IN(_method) Trace(_method, true)
82 :
83 : #define NS_FRAME_TRACE_OUT(_method) Trace(_method, false)
84 :
85 : // XXX remove me
86 : #define NS_FRAME_TRACE_MSG(_bit,_args) \
87 : PR_BEGIN_MACRO \
88 : if (NS_FRAME_LOG_TEST(nsFrame::GetLogModuleInfo(),_bit)) { \
89 : TraceMsg _args; \
90 : } \
91 : PR_END_MACRO
92 :
93 : #define NS_FRAME_TRACE(_bit,_args) \
94 : PR_BEGIN_MACRO \
95 : if (NS_FRAME_LOG_TEST(nsFrame::GetLogModuleInfo(),_bit)) { \
96 : TraceMsg _args; \
97 : } \
98 : PR_END_MACRO
99 :
100 : #define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, true)
101 :
102 : #define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
103 : Trace(_method, false, _status)
104 :
105 : #else
106 : #define NS_FRAME_TRACE(_bits,_args)
107 : #define NS_FRAME_TRACE_IN(_method)
108 : #define NS_FRAME_TRACE_OUT(_method)
109 : #define NS_FRAME_TRACE_MSG(_bits,_args)
110 : #define NS_FRAME_TRACE_REFLOW_IN(_method)
111 : #define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
112 : #endif
113 :
114 : // Frame allocation boilerplate macros. Every subclass of nsFrame
115 : // must define its own operator new and GetAllocatedSize. If they do
116 : // not, the per-frame recycler lists in nsPresArena will not work
117 : // correctly, with potentially catastrophic consequences (not enough
118 : // memory is allocated for a frame object).
119 :
120 : #define NS_DECL_FRAMEARENA_HELPERS \
121 : NS_MUST_OVERRIDE void* operator new(size_t, nsIPresShell*); \
122 : virtual NS_MUST_OVERRIDE nsQueryFrame::FrameIID GetFrameId();
123 :
124 : #define NS_IMPL_FRAMEARENA_HELPERS(class) \
125 : void* class::operator new(size_t sz, nsIPresShell* aShell) \
126 : { return aShell->AllocateFrame(nsQueryFrame::class##_id, sz); } \
127 : nsQueryFrame::FrameIID class::GetFrameId() \
128 : { return nsQueryFrame::class##_id; }
129 :
130 : //----------------------------------------------------------------------
131 :
132 : struct nsBoxLayoutMetrics;
133 :
134 : /**
135 : * Implementation of a simple frame that's not splittable and has no
136 : * child frames.
137 : *
138 : * Sets the NS_FRAME_SYNCHRONIZE_FRAME_AND_VIEW bit, so the default
139 : * behavior is to keep the frame and view position and size in sync.
140 : */
141 : class nsFrame : public nsBox
142 : {
143 : public:
144 : /**
145 : * Create a new "empty" frame that maps a given piece of content into a
146 : * 0,0 area.
147 : */
148 : friend nsIFrame* NS_NewEmptyFrame(nsIPresShell* aShell,
149 : nsStyleContext* aContext);
150 :
151 : private:
152 : // Left undefined; nsFrame objects are never allocated from the heap.
153 : void* operator new(size_t sz) CPP_THROW_NEW;
154 :
155 : protected:
156 : // Overridden to prevent the global delete from being called, since
157 : // the memory came out of an arena instead of the heap.
158 : //
159 : // Ideally this would be private and undefined, like the normal
160 : // operator new. Unfortunately, the C++ standard requires an
161 : // overridden operator delete to be accessible to any subclass that
162 : // defines a virtual destructor, so we can only make it protected;
163 : // worse, some C++ compilers will synthesize calls to this function
164 : // from the "deleting destructors" that they emit in case of
165 : // delete-expressions, so it can't even be undefined.
166 : void operator delete(void* aPtr, size_t sz);
167 :
168 : public:
169 :
170 : // nsQueryFrame
171 : NS_DECL_QUERYFRAME
172 : NS_DECL_FRAMEARENA_HELPERS
173 :
174 : // nsIFrame
175 : NS_IMETHOD Init(nsIContent* aContent,
176 : nsIFrame* aParent,
177 : nsIFrame* asPrevInFlow);
178 : NS_IMETHOD SetInitialChildList(ChildListID aListID,
179 : nsFrameList& aChildList);
180 : NS_IMETHOD AppendFrames(ChildListID aListID,
181 : nsFrameList& aFrameList);
182 : NS_IMETHOD InsertFrames(ChildListID aListID,
183 : nsIFrame* aPrevFrame,
184 : nsFrameList& aFrameList);
185 : NS_IMETHOD RemoveFrame(ChildListID aListID,
186 : nsIFrame* aOldFrame);
187 : virtual void DestroyFrom(nsIFrame* aDestructRoot);
188 : virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const;
189 : virtual void SetAdditionalStyleContext(PRInt32 aIndex,
190 : nsStyleContext* aStyleContext);
191 : virtual void SetParent(nsIFrame* aParent);
192 : virtual nscoord GetBaseline() const;
193 : virtual const nsFrameList& GetChildList(ChildListID aListID) const;
194 : virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
195 :
196 : NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
197 : nsGUIEvent* aEvent,
198 : nsEventStatus* aEventStatus);
199 : NS_IMETHOD GetContentForEvent(nsEvent* aEvent,
200 : nsIContent** aContent);
201 : NS_IMETHOD GetCursor(const nsPoint& aPoint,
202 : nsIFrame::Cursor& aCursor);
203 :
204 : NS_IMETHOD GetPointFromOffset(PRInt32 inOffset,
205 : nsPoint* outPoint);
206 :
207 : NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset,
208 : bool inHint,
209 : PRInt32* outFrameContentOffset,
210 : nsIFrame* *outChildFrame);
211 :
212 : static nsresult GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
213 : nsPeekOffsetStruct *aPos,
214 : nsIFrame *aBlockFrame,
215 : PRInt32 aLineStart,
216 : PRInt8 aOutSideLimit
217 : );
218 :
219 : NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo);
220 : NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
221 : nsIAtom* aAttribute,
222 : PRInt32 aModType);
223 : virtual nsSplittableType GetSplittableType() const;
224 : virtual nsIFrame* GetPrevContinuation() const;
225 : NS_IMETHOD SetPrevContinuation(nsIFrame*);
226 : virtual nsIFrame* GetNextContinuation() const;
227 : NS_IMETHOD SetNextContinuation(nsIFrame*);
228 : virtual nsIFrame* GetPrevInFlowVirtual() const;
229 : NS_IMETHOD SetPrevInFlow(nsIFrame*);
230 : virtual nsIFrame* GetNextInFlowVirtual() const;
231 : NS_IMETHOD SetNextInFlow(nsIFrame*);
232 : NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const;
233 : virtual nsIAtom* GetType() const;
234 :
235 : NS_IMETHOD IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const;
236 :
237 : NS_IMETHOD GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon);
238 :
239 : virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
240 : virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
241 : bool aRespectClusters = true);
242 : virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
243 : PRInt32* aOffset, PeekWordState *aState);
244 : /**
245 : * Check whether we should break at a boundary between punctuation and
246 : * non-punctuation. Only call it at a punctuation boundary
247 : * (i.e. exactly one of the previous and next characters are punctuation).
248 : * @param aForward true if we're moving forward in content order
249 : * @param aPunctAfter true if the next character is punctuation
250 : * @param aWhitespaceAfter true if the next character is whitespace
251 : */
252 : bool BreakWordBetweenPunctuation(const PeekWordState* aState,
253 : bool aForward,
254 : bool aPunctAfter, bool aWhitespaceAfter,
255 : bool aIsKeyboardSelect);
256 :
257 : NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, bool aRecurse, bool *aFinished, bool *_retval);
258 :
259 : NS_IMETHOD GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const;
260 : virtual void ChildIsDirty(nsIFrame* aChild);
261 :
262 : #ifdef ACCESSIBILITY
263 : virtual already_AddRefed<nsAccessible> CreateAccessible();
264 : #endif
265 :
266 0 : virtual nsIFrame* GetParentStyleContextFrame() const {
267 0 : return DoGetParentStyleContextFrame();
268 : }
269 :
270 : /**
271 : * Do the work for getting the parent style context frame so that
272 : * other frame's |GetParentStyleContextFrame| methods can call this
273 : * method on *another* frame. (This function handles out-of-flow
274 : * frames by using the frame manager's placeholder map and it also
275 : * handles block-within-inline and generated content wrappers.)
276 : */
277 : nsIFrame* DoGetParentStyleContextFrame() const;
278 :
279 : virtual bool IsEmpty();
280 : virtual bool IsSelfEmpty();
281 :
282 : virtual void MarkIntrinsicWidthsDirty();
283 : virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
284 : virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
285 : virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
286 : InlineMinWidthData *aData);
287 : virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
288 : InlinePrefWidthData *aData);
289 : virtual IntrinsicWidthOffsetData
290 : IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext);
291 : virtual IntrinsicSize GetIntrinsicSize();
292 : virtual nsSize GetIntrinsicRatio();
293 :
294 : virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
295 : nsSize aCBSize, nscoord aAvailableWidth,
296 : nsSize aMargin, nsSize aBorder, nsSize aPadding,
297 : bool aShrinkWrap);
298 :
299 : // Compute tight bounds assuming this frame honours its border, background
300 : // and outline, its children's tight bounds, and nothing else.
301 : nsRect ComputeSimpleTightBounds(gfxContext* aContext) const;
302 :
303 : /**
304 : * A helper, used by |nsFrame::ComputeSize| (for frames that need to
305 : * override only this part of ComputeSize), that computes the size
306 : * that should be returned when 'width', 'height', and
307 : * min/max-width/height are all 'auto' or equivalent.
308 : *
309 : * In general, frames that can accept any computed width/height should
310 : * override only ComputeAutoSize, and frames that cannot do so need to
311 : * override ComputeSize to enforce their width/height invariants.
312 : *
313 : * Implementations may optimize by returning a garbage width if
314 : * GetStylePosition()->mWidth.GetUnit() != eStyleUnit_Auto, and
315 : * likewise for height, since in such cases the result is guaranteed
316 : * to be unused.
317 : */
318 : virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
319 : nsSize aCBSize, nscoord aAvailableWidth,
320 : nsSize aMargin, nsSize aBorder,
321 : nsSize aPadding, bool aShrinkWrap);
322 :
323 : /**
324 : * Utility function for ComputeAutoSize implementations. Return
325 : * max(GetMinWidth(), min(aWidthInCB, GetPrefWidth()))
326 : */
327 : nscoord ShrinkWidthToFit(nsRenderingContext *aRenderingContext,
328 : nscoord aWidthInCB);
329 :
330 : NS_IMETHOD WillReflow(nsPresContext* aPresContext);
331 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
332 : nsHTMLReflowMetrics& aDesiredSize,
333 : const nsHTMLReflowState& aReflowState,
334 : nsReflowStatus& aStatus);
335 : NS_IMETHOD DidReflow(nsPresContext* aPresContext,
336 : const nsHTMLReflowState* aReflowState,
337 : nsDidReflowStatus aStatus);
338 : void ReflowAbsoluteFrames(nsPresContext* aPresContext,
339 : nsHTMLReflowMetrics& aDesiredSize,
340 : const nsHTMLReflowState& aReflowState,
341 : nsReflowStatus& aStatus);
342 : void FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext,
343 : nsHTMLReflowMetrics& aDesiredSize,
344 : const nsHTMLReflowState& aReflowState,
345 : nsReflowStatus& aStatus);
346 : void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
347 : virtual bool CanContinueTextRun() const;
348 :
349 : virtual bool UpdateOverflow();
350 :
351 : // Selection Methods
352 : // XXX Doc me... (in nsIFrame.h puhleeze)
353 : // XXX If these are selection specific, then the name should imply selection
354 : // rather than generic event processing, e.g., SelectionHandlePress...
355 : NS_IMETHOD HandlePress(nsPresContext* aPresContext,
356 : nsGUIEvent * aEvent,
357 : nsEventStatus* aEventStatus);
358 :
359 : NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
360 : nsGUIEvent * aEvent,
361 : nsEventStatus* aEventStatus,
362 : bool aControlHeld);
363 :
364 : NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
365 : nsGUIEvent * aEvent,
366 : nsEventStatus* aEventStatus);
367 :
368 : NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
369 : nsGUIEvent * aEvent,
370 : nsEventStatus* aEventStatus);
371 :
372 : NS_IMETHOD PeekBackwardAndForward(nsSelectionAmount aAmountBack,
373 : nsSelectionAmount aAmountForward,
374 : PRInt32 aStartPos,
375 : nsPresContext* aPresContext,
376 : bool aJumpLines,
377 : bool aMultipleSelection);
378 :
379 :
380 : // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
381 : // in this function assumes there is no child frame that can be targeted.
382 : virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
383 :
384 : // Box layout methods
385 : virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
386 : virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
387 : virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
388 : virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState);
389 : virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState);
390 :
391 : // We compute and store the HTML content's overflow area. So don't
392 : // try to compute it in the box code.
393 0 : virtual bool ComputesOwnOverflowArea() { return true; }
394 :
395 : //--------------------------------------------------
396 : // Additional methods
397 :
398 : /**
399 : * Helper method to invalidate portions of a standard container frame if the
400 : * desired size indicates that the size has changed (specifically border,
401 : * background and outline).
402 : * We assume that the difference between the old frame area and the new
403 : * frame area is invalidated by some other means.
404 : * @param aDesiredSize the new size of the frame
405 : */
406 : void CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize);
407 :
408 : // Helper function that tests if the frame tree is too deep; if it is
409 : // it marks the frame as "unflowable", zeroes out the metrics, sets
410 : // the reflow status, and returns true. Otherwise, the frame is
411 : // unmarked "unflowable" and the metrics and reflow status are not
412 : // touched and false is returned.
413 : bool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
414 : nsHTMLReflowMetrics& aMetrics,
415 : nsReflowStatus& aStatus);
416 :
417 : // Incorporate the child overflow areas into aOverflowAreas.
418 : // If the child does not have a overflow, use the child area.
419 : void ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
420 : nsIFrame* aChildFrame);
421 :
422 : virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const;
423 :
424 :
425 : #ifdef NS_DEBUG
426 : /**
427 : * Tracing method that writes a method enter/exit routine to the
428 : * nspr log using the nsIFrame log module. The tracing is only
429 : * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
430 : * level field.
431 : */
432 : void Trace(const char* aMethod, bool aEnter);
433 : void Trace(const char* aMethod, bool aEnter, nsReflowStatus aStatus);
434 : void TraceMsg(const char* fmt, ...);
435 :
436 : // Helper function that verifies that each frame in the list has the
437 : // NS_FRAME_IS_DIRTY bit set
438 : static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
439 :
440 : // Helper function to return the index in parent of the frame's content
441 : // object. Returns -1 on error or if the frame doesn't have a content object
442 : static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
443 :
444 0 : static void IndentBy(FILE* out, PRInt32 aIndent) {
445 0 : while (--aIndent >= 0) fputs(" ", out);
446 0 : }
447 :
448 0 : void ListTag(FILE* out) const {
449 0 : ListTag(out, this);
450 0 : }
451 :
452 0 : static void ListTag(FILE* out, const nsIFrame* aFrame) {
453 0 : nsAutoString tmp;
454 0 : aFrame->GetFrameName(tmp);
455 0 : fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
456 0 : fprintf(out, "@%p", static_cast<const void*>(aFrame));
457 0 : }
458 :
459 : static void XMLQuote(nsString& aString);
460 :
461 : /**
462 : * Dump out the "base classes" regression data. This should dump
463 : * out the interior data, not the "frame" XML container. And it
464 : * should call the base classes same named method before doing
465 : * anything specific in a derived class. This means that derived
466 : * classes need not override DumpRegressionData unless they need
467 : * some custom behavior that requires changing how the outer "frame"
468 : * XML container is dumped.
469 : */
470 : virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent);
471 :
472 : nsresult MakeFrameName(const nsAString& aKind, nsAString& aResult) const;
473 :
474 : // Display Reflow Debugging
475 : static void* DisplayReflowEnter(nsPresContext* aPresContext,
476 : nsIFrame* aFrame,
477 : const nsHTMLReflowState& aReflowState);
478 : static void* DisplayLayoutEnter(nsIFrame* aFrame);
479 : static void* DisplayIntrinsicWidthEnter(nsIFrame* aFrame,
480 : const char* aType);
481 : static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
482 : const char* aType);
483 : static void DisplayReflowExit(nsPresContext* aPresContext,
484 : nsIFrame* aFrame,
485 : nsHTMLReflowMetrics& aMetrics,
486 : PRUint32 aStatus,
487 : void* aFrameTreeNode);
488 : static void DisplayLayoutExit(nsIFrame* aFrame,
489 : void* aFrameTreeNode);
490 : static void DisplayIntrinsicWidthExit(nsIFrame* aFrame,
491 : const char* aType,
492 : nscoord aResult,
493 : void* aFrameTreeNode);
494 : static void DisplayIntrinsicSizeExit(nsIFrame* aFrame,
495 : const char* aType,
496 : nsSize aResult,
497 : void* aFrameTreeNode);
498 :
499 : static void DisplayReflowStartup();
500 : static void DisplayReflowShutdown();
501 : #endif
502 :
503 : static void ShutdownLayerActivityTimer();
504 :
505 : /**
506 : * Adds display item for standard CSS background if necessary.
507 : * Does not check IsVisibleForPainting.
508 : * @param aForceBackground draw the background even if the frame
509 : * background style appears to have no background --- this is useful
510 : * for frames that might receive a propagated background via
511 : * nsCSSRendering::FindBackground
512 : */
513 : nsresult DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
514 : const nsDisplayListSet& aLists,
515 : bool aForceBackground = false);
516 : /**
517 : * Adds display items for standard CSS borders, background and outline for
518 : * for this frame, as necessary. Checks IsVisibleForPainting and won't
519 : * display anything if the frame is not visible.
520 : * @param aForceBackground draw the background even if the frame
521 : * background style appears to have no background --- this is useful
522 : * for frames that might receive a propagated background via
523 : * nsCSSRendering::FindBackground
524 : */
525 : nsresult DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
526 : const nsDisplayListSet& aLists,
527 : bool aForceBackground = false);
528 : /**
529 : * Add a display item for the CSS outline. Does not check visibility.
530 : */
531 : nsresult DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
532 : const nsDisplayListSet& aLists);
533 : /**
534 : * Add a display item for the CSS outline, after calling
535 : * IsVisibleForPainting to confirm we are visible.
536 : */
537 : nsresult DisplayOutline(nsDisplayListBuilder* aBuilder,
538 : const nsDisplayListSet& aLists);
539 :
540 : /**
541 : * Adjust the given parent frame to the right style context parent frame for
542 : * the child, given the pseudo-type of the prospective child. This handles
543 : * things like walking out of table pseudos and so forth.
544 : *
545 : * @param aProspectiveParent what GetParent() on the child returns.
546 : * Must not be null.
547 : * @param aChildPseudo the child's pseudo type, if any.
548 : */
549 : static nsIFrame*
550 : CorrectStyleParentFrame(nsIFrame* aProspectiveParent, nsIAtom* aChildPseudo);
551 :
552 : protected:
553 : // Protected constructor and destructor
554 : nsFrame(nsStyleContext* aContext);
555 : virtual ~nsFrame();
556 :
557 : /**
558 : * To be called by |BuildDisplayLists| of this class or derived classes to add
559 : * a translucent overlay if this frame's content is selected.
560 : * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
561 : * which kind of content this is for
562 : */
563 : nsresult DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
564 : nsDisplayList* aList, PRUint16 aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
565 :
566 : PRInt16 DisplaySelection(nsPresContext* aPresContext, bool isOkToTurnOn = false);
567 :
568 : // Style post processing hook
569 : virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
570 :
571 : public:
572 : //given a frame five me the first/last leaf available
573 : //XXX Robert O'Callahan wants to move these elsewhere
574 : static void GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
575 : static void GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
576 :
577 : // Return the line number of the aFrame, and (optionally) the containing block
578 : // frame.
579 : // If aScrollLock is true, don't break outside scrollframes when looking for a
580 : // containing block frame.
581 : static PRInt32 GetLineNumber(nsIFrame *aFrame,
582 : bool aLockScroll,
583 : nsIFrame** aContainingBlock = nsnull);
584 :
585 : /**
586 : * Returns true if aFrame should apply overflow clipping.
587 : */
588 0 : static bool ApplyOverflowClipping(const nsIFrame* aFrame,
589 : const nsStyleDisplay* aDisp)
590 : {
591 : // clip overflow:-moz-hidden-unscrollable ...
592 0 : if (NS_UNLIKELY(aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP)) {
593 0 : return true;
594 : }
595 :
596 : // and overflow:hidden that we should interpret as -moz-hidden-unscrollable
597 0 : if (aDisp->mOverflowX == NS_STYLE_OVERFLOW_HIDDEN &&
598 : aDisp->mOverflowY == NS_STYLE_OVERFLOW_HIDDEN) {
599 : // REVIEW: these are the frame types that set up clipping.
600 0 : nsIAtom* type = aFrame->GetType();
601 0 : if (type == nsGkAtoms::tableFrame ||
602 : type == nsGkAtoms::tableCellFrame ||
603 : type == nsGkAtoms::bcTableCellFrame) {
604 0 : return true;
605 : }
606 : }
607 :
608 : // If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
609 : // set, then we want to clip our overflow.
610 : return
611 0 : aFrame->PresContext()->IsPaginated() &&
612 0 : (aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0 &&
613 0 : aFrame->GetType() == nsGkAtoms::blockFrame;
614 : }
615 :
616 : protected:
617 :
618 : // Test if we are selecting a table object:
619 : // Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
620 : // during a mouse click or drag. Exception is using Shift+click when
621 : // already in "table/cell selection mode" to extend a block selection
622 : // Get the parent content node and offset of the frame
623 : // of the enclosing cell or table (if not inside a cell)
624 : // aTarget tells us what table element to select (currently only cell and table supported)
625 : // (enums for this are defined in nsIFrame.h)
626 : NS_IMETHOD GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
627 : nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
628 : nsIContent **aParentContent, PRInt32 *aContentOffset,
629 : PRInt32 *aTarget);
630 :
631 : // Fills aCursor with the appropriate information from ui
632 : static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
633 : nsIFrame::Cursor& aCursor);
634 : NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
635 :
636 : #ifdef DEBUG_LAYOUT
637 : virtual void GetBoxName(nsAutoString& aName);
638 : #endif
639 :
640 : void InitBoxMetrics(bool aClear);
641 : nsBoxLayoutMetrics* BoxMetrics() const;
642 :
643 : // Fire DOM event. If no aContent argument use frame's mContent.
644 : void FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent = nsnull);
645 :
646 : private:
647 : nsresult BoxReflow(nsBoxLayoutState& aState,
648 : nsPresContext* aPresContext,
649 : nsHTMLReflowMetrics& aDesiredSize,
650 : nsRenderingContext* aRenderingContext,
651 : nscoord aX,
652 : nscoord aY,
653 : nscoord aWidth,
654 : nscoord aHeight,
655 : bool aMoveFrame = true);
656 :
657 : NS_IMETHODIMP RefreshSizeCache(nsBoxLayoutState& aState);
658 :
659 : virtual nsILineIterator* GetLineIterator();
660 :
661 : #ifdef NS_DEBUG
662 : public:
663 : // Formerly the nsIFrameDebug interface
664 :
665 : NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
666 : /**
667 : * lists the frames beginning from the root frame
668 : * - calls root frame's List(...)
669 : */
670 : static void RootFrameList(nsPresContext* aPresContext,
671 : FILE* out, PRInt32 aIndent);
672 :
673 : static void DumpFrameTree(nsIFrame* aFrame);
674 :
675 : /**
676 : * Get a printable from of the name of the frame type.
677 : * XXX This should be eliminated and we use GetType() instead...
678 : */
679 : NS_IMETHOD GetFrameName(nsAString& aResult) const;
680 : /**
681 : * Return the state bits that are relevant to regression tests (that
682 : * is, those bits which indicate a real difference when they differ
683 : */
684 : NS_IMETHOD_(nsFrameState) GetDebugStateBits() const;
685 : /**
686 : * Called to dump out regression data that describes the layout
687 : * of the frame and its children, and so on. The format of the
688 : * data is dictated to be XML (using a specific DTD); the
689 : * specific kind of data dumped is up to the frame itself, with
690 : * the caveat that some base types are defined.
691 : * For more information, see XXX.
692 : */
693 : NS_IMETHOD DumpRegressionData(nsPresContext* aPresContext,
694 : FILE* out, PRInt32 aIndent);
695 :
696 : /**
697 : * See if style tree verification is enabled. To enable style tree
698 : * verification add "styleverifytree:1" to your NSPR_LOG_MODULES
699 : * environment variable (any non-zero debug level will work). Or,
700 : * call SetVerifyStyleTreeEnable with true.
701 : */
702 : static bool GetVerifyStyleTreeEnable();
703 :
704 : /**
705 : * Set the verify-style-tree enable flag.
706 : */
707 : static void SetVerifyStyleTreeEnable(bool aEnabled);
708 :
709 : /**
710 : * The frame class and related classes share an nspr log module
711 : * for logging frame activity.
712 : *
713 : * Note: the log module is created during library initialization which
714 : * means that you cannot perform logging before then.
715 : */
716 : static PRLogModuleInfo* GetLogModuleInfo();
717 :
718 : // Show frame borders when rendering
719 : static void ShowFrameBorders(bool aEnable);
720 : static bool GetShowFrameBorders();
721 :
722 : // Show frame border of event target
723 : static void ShowEventTargetFrameBorder(bool aEnable);
724 : static bool GetShowEventTargetFrameBorder();
725 :
726 : #endif
727 : #ifdef MOZ_DUMP_PAINTING
728 : public:
729 :
730 : static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
731 : const nsDisplayList& aList,
732 : FILE* aFile = stdout);
733 :
734 : #endif
735 : };
736 :
737 : // Start Display Reflow Debugging
738 : #ifdef DEBUG
739 :
740 : struct DR_cookie {
741 : DR_cookie(nsPresContext* aPresContext,
742 : nsIFrame* aFrame,
743 : const nsHTMLReflowState& aReflowState,
744 : nsHTMLReflowMetrics& aMetrics,
745 : nsReflowStatus& aStatus);
746 : ~DR_cookie();
747 : void Change() const;
748 :
749 : nsPresContext* mPresContext;
750 : nsIFrame* mFrame;
751 : const nsHTMLReflowState& mReflowState;
752 : nsHTMLReflowMetrics& mMetrics;
753 : nsReflowStatus& mStatus;
754 : void* mValue;
755 : };
756 :
757 : struct DR_layout_cookie {
758 : DR_layout_cookie(nsIFrame* aFrame);
759 : ~DR_layout_cookie();
760 :
761 : nsIFrame* mFrame;
762 : void* mValue;
763 : };
764 :
765 : struct DR_intrinsic_width_cookie {
766 : DR_intrinsic_width_cookie(nsIFrame* aFrame, const char* aType,
767 : nscoord& aResult);
768 : ~DR_intrinsic_width_cookie();
769 :
770 : nsIFrame* mFrame;
771 : const char* mType;
772 : nscoord& mResult;
773 : void* mValue;
774 : };
775 :
776 : struct DR_intrinsic_size_cookie {
777 : DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
778 : nsSize& aResult);
779 : ~DR_intrinsic_size_cookie();
780 :
781 : nsIFrame* mFrame;
782 : const char* mType;
783 : nsSize& mResult;
784 : void* mValue;
785 : };
786 :
787 : struct DR_init_constraints_cookie {
788 : DR_init_constraints_cookie(nsIFrame* aFrame, nsHTMLReflowState* aState,
789 : nscoord aCBWidth, nscoord aCBHeight,
790 : const nsMargin* aBorder,
791 : const nsMargin* aPadding);
792 : ~DR_init_constraints_cookie();
793 :
794 : nsIFrame* mFrame;
795 : nsHTMLReflowState* mState;
796 : void* mValue;
797 : };
798 :
799 : struct DR_init_offsets_cookie {
800 : DR_init_offsets_cookie(nsIFrame* aFrame, nsCSSOffsetState* aState,
801 : nscoord aCBWidth, const nsMargin* aBorder,
802 : const nsMargin* aPadding);
803 : ~DR_init_offsets_cookie();
804 :
805 : nsIFrame* mFrame;
806 : nsCSSOffsetState* mState;
807 : void* mValue;
808 : };
809 :
810 : struct DR_init_type_cookie {
811 : DR_init_type_cookie(nsIFrame* aFrame, nsHTMLReflowState* aState);
812 : ~DR_init_type_cookie();
813 :
814 : nsIFrame* mFrame;
815 : nsHTMLReflowState* mState;
816 : void* mValue;
817 : };
818 :
819 : #define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status) \
820 : DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status);
821 : #define DISPLAY_REFLOW_CHANGE() \
822 : dr_cookie.Change();
823 : #define DISPLAY_LAYOUT(dr_frame) \
824 : DR_layout_cookie dr_cookie(dr_frame);
825 : #define DISPLAY_MIN_WIDTH(dr_frame, dr_result) \
826 : DR_intrinsic_width_cookie dr_cookie(dr_frame, "Min", dr_result)
827 : #define DISPLAY_PREF_WIDTH(dr_frame, dr_result) \
828 : DR_intrinsic_width_cookie dr_cookie(dr_frame, "Pref", dr_result)
829 : #define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
830 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
831 : #define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
832 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
833 : #define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
834 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
835 : #define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, \
836 : dr_bdr, dr_pad) \
837 : DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \
838 : dr_bdr, dr_pad)
839 : #define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad) \
840 : DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad)
841 : #define DISPLAY_INIT_TYPE(dr_frame, dr_result) \
842 : DR_init_type_cookie dr_cookie(dr_frame, dr_result)
843 :
844 : #else
845 :
846 : #define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status)
847 : #define DISPLAY_REFLOW_CHANGE()
848 : #define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
849 : #define DISPLAY_MIN_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
850 : #define DISPLAY_PREF_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
851 : #define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
852 : #define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
853 : #define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
854 : #define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, \
855 : dr_bdr, dr_pad) \
856 : PR_BEGIN_MACRO PR_END_MACRO
857 : #define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad) \
858 : PR_BEGIN_MACRO PR_END_MACRO
859 : #define DISPLAY_INIT_TYPE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
860 :
861 : #endif
862 : // End Display Reflow Debugging
863 :
864 : // similar to NS_ENSURE_TRUE but with no return value
865 : #define ENSURE_TRUE(x) \
866 : PR_BEGIN_MACRO \
867 : if (!(x)) { \
868 : NS_WARNING("ENSURE_TRUE(" #x ") failed"); \
869 : return; \
870 : } \
871 : PR_END_MACRO
872 : #endif /* nsFrame_h___ */
|