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 : bool aConstrainHeight = true);
343 : void FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext,
344 : nsHTMLReflowMetrics& aDesiredSize,
345 : const nsHTMLReflowState& aReflowState,
346 : nsReflowStatus& aStatus,
347 : bool aConstrainHeight = true);
348 : void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
349 : virtual bool CanContinueTextRun() const;
350 :
351 : virtual bool UpdateOverflow();
352 :
353 : // Selection Methods
354 : // XXX Doc me... (in nsIFrame.h puhleeze)
355 : // XXX If these are selection specific, then the name should imply selection
356 : // rather than generic event processing, e.g., SelectionHandlePress...
357 : NS_IMETHOD HandlePress(nsPresContext* aPresContext,
358 : nsGUIEvent * aEvent,
359 : nsEventStatus* aEventStatus);
360 :
361 : NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
362 : nsGUIEvent * aEvent,
363 : nsEventStatus* aEventStatus,
364 : bool aControlHeld);
365 :
366 : NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
367 : nsGUIEvent * aEvent,
368 : nsEventStatus* aEventStatus);
369 :
370 : NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
371 : nsGUIEvent * aEvent,
372 : nsEventStatus* aEventStatus);
373 :
374 : NS_IMETHOD PeekBackwardAndForward(nsSelectionAmount aAmountBack,
375 : nsSelectionAmount aAmountForward,
376 : PRInt32 aStartPos,
377 : nsPresContext* aPresContext,
378 : bool aJumpLines,
379 : bool aMultipleSelection);
380 :
381 :
382 : // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
383 : // in this function assumes there is no child frame that can be targeted.
384 : virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
385 :
386 : // Box layout methods
387 : virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
388 : virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
389 : virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
390 : virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState);
391 : virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState);
392 :
393 : // We compute and store the HTML content's overflow area. So don't
394 : // try to compute it in the box code.
395 0 : virtual bool ComputesOwnOverflowArea() { return true; }
396 :
397 : //--------------------------------------------------
398 : // Additional methods
399 :
400 : /**
401 : * Helper method to invalidate portions of a standard container frame if the
402 : * desired size indicates that the size has changed (specifically border,
403 : * background and outline).
404 : * We assume that the difference between the old frame area and the new
405 : * frame area is invalidated by some other means.
406 : * @param aDesiredSize the new size of the frame
407 : */
408 : void CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize);
409 :
410 : // Helper function that tests if the frame tree is too deep; if it is
411 : // it marks the frame as "unflowable", zeroes out the metrics, sets
412 : // the reflow status, and returns true. Otherwise, the frame is
413 : // unmarked "unflowable" and the metrics and reflow status are not
414 : // touched and false is returned.
415 : bool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
416 : nsHTMLReflowMetrics& aMetrics,
417 : nsReflowStatus& aStatus);
418 :
419 : // Incorporate the child overflow areas into aOverflowAreas.
420 : // If the child does not have a overflow, use the child area.
421 : void ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
422 : nsIFrame* aChildFrame);
423 :
424 : virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const;
425 :
426 :
427 : #ifdef NS_DEBUG
428 : /**
429 : * Tracing method that writes a method enter/exit routine to the
430 : * nspr log using the nsIFrame log module. The tracing is only
431 : * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
432 : * level field.
433 : */
434 : void Trace(const char* aMethod, bool aEnter);
435 : void Trace(const char* aMethod, bool aEnter, nsReflowStatus aStatus);
436 : void TraceMsg(const char* fmt, ...);
437 :
438 : // Helper function that verifies that each frame in the list has the
439 : // NS_FRAME_IS_DIRTY bit set
440 : static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
441 :
442 : // Helper function to return the index in parent of the frame's content
443 : // object. Returns -1 on error or if the frame doesn't have a content object
444 : static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
445 :
446 0 : static void IndentBy(FILE* out, PRInt32 aIndent) {
447 0 : while (--aIndent >= 0) fputs(" ", out);
448 0 : }
449 :
450 0 : void ListTag(FILE* out) const {
451 0 : ListTag(out, this);
452 0 : }
453 :
454 0 : static void ListTag(FILE* out, const nsIFrame* aFrame) {
455 0 : nsAutoString tmp;
456 0 : aFrame->GetFrameName(tmp);
457 0 : fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
458 0 : fprintf(out, "@%p", static_cast<const void*>(aFrame));
459 0 : }
460 :
461 : static void XMLQuote(nsString& aString);
462 :
463 : /**
464 : * Dump out the "base classes" regression data. This should dump
465 : * out the interior data, not the "frame" XML container. And it
466 : * should call the base classes same named method before doing
467 : * anything specific in a derived class. This means that derived
468 : * classes need not override DumpRegressionData unless they need
469 : * some custom behavior that requires changing how the outer "frame"
470 : * XML container is dumped.
471 : */
472 : virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent);
473 :
474 : nsresult MakeFrameName(const nsAString& aKind, nsAString& aResult) const;
475 :
476 : // Display Reflow Debugging
477 : static void* DisplayReflowEnter(nsPresContext* aPresContext,
478 : nsIFrame* aFrame,
479 : const nsHTMLReflowState& aReflowState);
480 : static void* DisplayLayoutEnter(nsIFrame* aFrame);
481 : static void* DisplayIntrinsicWidthEnter(nsIFrame* aFrame,
482 : const char* aType);
483 : static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
484 : const char* aType);
485 : static void DisplayReflowExit(nsPresContext* aPresContext,
486 : nsIFrame* aFrame,
487 : nsHTMLReflowMetrics& aMetrics,
488 : PRUint32 aStatus,
489 : void* aFrameTreeNode);
490 : static void DisplayLayoutExit(nsIFrame* aFrame,
491 : void* aFrameTreeNode);
492 : static void DisplayIntrinsicWidthExit(nsIFrame* aFrame,
493 : const char* aType,
494 : nscoord aResult,
495 : void* aFrameTreeNode);
496 : static void DisplayIntrinsicSizeExit(nsIFrame* aFrame,
497 : const char* aType,
498 : nsSize aResult,
499 : void* aFrameTreeNode);
500 :
501 : static void DisplayReflowStartup();
502 : static void DisplayReflowShutdown();
503 : #endif
504 :
505 : static void ShutdownLayerActivityTimer();
506 :
507 : /**
508 : * Adds display item for standard CSS background if necessary.
509 : * Does not check IsVisibleForPainting.
510 : * @param aForceBackground draw the background even if the frame
511 : * background style appears to have no background --- this is useful
512 : * for frames that might receive a propagated background via
513 : * nsCSSRendering::FindBackground
514 : */
515 : nsresult DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
516 : const nsDisplayListSet& aLists,
517 : bool aForceBackground = false);
518 : /**
519 : * Adds display items for standard CSS borders, background and outline for
520 : * for this frame, as necessary. Checks IsVisibleForPainting and won't
521 : * display anything if the frame is not visible.
522 : * @param aForceBackground draw the background even if the frame
523 : * background style appears to have no background --- this is useful
524 : * for frames that might receive a propagated background via
525 : * nsCSSRendering::FindBackground
526 : */
527 : nsresult DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
528 : const nsDisplayListSet& aLists,
529 : bool aForceBackground = false);
530 : /**
531 : * Add a display item for the CSS outline. Does not check visibility.
532 : */
533 : nsresult DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
534 : const nsDisplayListSet& aLists);
535 : /**
536 : * Add a display item for the CSS outline, after calling
537 : * IsVisibleForPainting to confirm we are visible.
538 : */
539 : nsresult DisplayOutline(nsDisplayListBuilder* aBuilder,
540 : const nsDisplayListSet& aLists);
541 :
542 : /**
543 : * Adjust the given parent frame to the right style context parent frame for
544 : * the child, given the pseudo-type of the prospective child. This handles
545 : * things like walking out of table pseudos and so forth.
546 : *
547 : * @param aProspectiveParent what GetParent() on the child returns.
548 : * Must not be null.
549 : * @param aChildPseudo the child's pseudo type, if any.
550 : */
551 : static nsIFrame*
552 : CorrectStyleParentFrame(nsIFrame* aProspectiveParent, nsIAtom* aChildPseudo);
553 :
554 : protected:
555 : // Protected constructor and destructor
556 : nsFrame(nsStyleContext* aContext);
557 : virtual ~nsFrame();
558 :
559 : /**
560 : * To be called by |BuildDisplayLists| of this class or derived classes to add
561 : * a translucent overlay if this frame's content is selected.
562 : * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
563 : * which kind of content this is for
564 : */
565 : nsresult DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
566 : nsDisplayList* aList, PRUint16 aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
567 :
568 : PRInt16 DisplaySelection(nsPresContext* aPresContext, bool isOkToTurnOn = false);
569 :
570 : // Style post processing hook
571 : virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
572 :
573 : public:
574 : //given a frame five me the first/last leaf available
575 : //XXX Robert O'Callahan wants to move these elsewhere
576 : static void GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
577 : static void GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
578 :
579 : // Return the line number of the aFrame, and (optionally) the containing block
580 : // frame.
581 : // If aScrollLock is true, don't break outside scrollframes when looking for a
582 : // containing block frame.
583 : static PRInt32 GetLineNumber(nsIFrame *aFrame,
584 : bool aLockScroll,
585 : nsIFrame** aContainingBlock = nsnull);
586 :
587 : /**
588 : * Returns true if aFrame should apply overflow clipping.
589 : */
590 0 : static bool ApplyOverflowClipping(const nsIFrame* aFrame,
591 : const nsStyleDisplay* aDisp)
592 : {
593 : // clip overflow:-moz-hidden-unscrollable ...
594 0 : if (NS_UNLIKELY(aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP)) {
595 0 : return true;
596 : }
597 :
598 : // and overflow:hidden that we should interpret as -moz-hidden-unscrollable
599 0 : if (aDisp->mOverflowX == NS_STYLE_OVERFLOW_HIDDEN &&
600 : aDisp->mOverflowY == NS_STYLE_OVERFLOW_HIDDEN) {
601 : // REVIEW: these are the frame types that set up clipping.
602 0 : nsIAtom* type = aFrame->GetType();
603 0 : if (type == nsGkAtoms::tableFrame ||
604 : type == nsGkAtoms::tableCellFrame ||
605 : type == nsGkAtoms::bcTableCellFrame) {
606 0 : return true;
607 : }
608 : }
609 :
610 : // If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
611 : // set, then we want to clip our overflow.
612 : return
613 0 : aFrame->PresContext()->IsPaginated() &&
614 0 : (aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0 &&
615 0 : aFrame->GetType() == nsGkAtoms::blockFrame;
616 : }
617 :
618 : protected:
619 :
620 : // Test if we are selecting a table object:
621 : // Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
622 : // during a mouse click or drag. Exception is using Shift+click when
623 : // already in "table/cell selection mode" to extend a block selection
624 : // Get the parent content node and offset of the frame
625 : // of the enclosing cell or table (if not inside a cell)
626 : // aTarget tells us what table element to select (currently only cell and table supported)
627 : // (enums for this are defined in nsIFrame.h)
628 : NS_IMETHOD GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
629 : nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
630 : nsIContent **aParentContent, PRInt32 *aContentOffset,
631 : PRInt32 *aTarget);
632 :
633 : // Fills aCursor with the appropriate information from ui
634 : static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
635 : nsIFrame::Cursor& aCursor);
636 : NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState);
637 :
638 : #ifdef DEBUG_LAYOUT
639 : virtual void GetBoxName(nsAutoString& aName);
640 : #endif
641 :
642 : void InitBoxMetrics(bool aClear);
643 : nsBoxLayoutMetrics* BoxMetrics() const;
644 :
645 : // Fire DOM event. If no aContent argument use frame's mContent.
646 : void FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent = nsnull);
647 :
648 : private:
649 : nsresult BoxReflow(nsBoxLayoutState& aState,
650 : nsPresContext* aPresContext,
651 : nsHTMLReflowMetrics& aDesiredSize,
652 : nsRenderingContext* aRenderingContext,
653 : nscoord aX,
654 : nscoord aY,
655 : nscoord aWidth,
656 : nscoord aHeight,
657 : bool aMoveFrame = true);
658 :
659 : NS_IMETHODIMP RefreshSizeCache(nsBoxLayoutState& aState);
660 :
661 : virtual nsILineIterator* GetLineIterator();
662 :
663 : #ifdef NS_DEBUG
664 : public:
665 : // Formerly the nsIFrameDebug interface
666 :
667 : NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
668 : /**
669 : * lists the frames beginning from the root frame
670 : * - calls root frame's List(...)
671 : */
672 : static void RootFrameList(nsPresContext* aPresContext,
673 : FILE* out, PRInt32 aIndent);
674 :
675 : static void DumpFrameTree(nsIFrame* aFrame);
676 :
677 : /**
678 : * Get a printable from of the name of the frame type.
679 : * XXX This should be eliminated and we use GetType() instead...
680 : */
681 : NS_IMETHOD GetFrameName(nsAString& aResult) const;
682 : /**
683 : * Return the state bits that are relevant to regression tests (that
684 : * is, those bits which indicate a real difference when they differ
685 : */
686 : NS_IMETHOD_(nsFrameState) GetDebugStateBits() const;
687 : /**
688 : * Called to dump out regression data that describes the layout
689 : * of the frame and its children, and so on. The format of the
690 : * data is dictated to be XML (using a specific DTD); the
691 : * specific kind of data dumped is up to the frame itself, with
692 : * the caveat that some base types are defined.
693 : * For more information, see XXX.
694 : */
695 : NS_IMETHOD DumpRegressionData(nsPresContext* aPresContext,
696 : FILE* out, PRInt32 aIndent);
697 :
698 : /**
699 : * See if style tree verification is enabled. To enable style tree
700 : * verification add "styleverifytree:1" to your NSPR_LOG_MODULES
701 : * environment variable (any non-zero debug level will work). Or,
702 : * call SetVerifyStyleTreeEnable with true.
703 : */
704 : static bool GetVerifyStyleTreeEnable();
705 :
706 : /**
707 : * Set the verify-style-tree enable flag.
708 : */
709 : static void SetVerifyStyleTreeEnable(bool aEnabled);
710 :
711 : /**
712 : * The frame class and related classes share an nspr log module
713 : * for logging frame activity.
714 : *
715 : * Note: the log module is created during library initialization which
716 : * means that you cannot perform logging before then.
717 : */
718 : static PRLogModuleInfo* GetLogModuleInfo();
719 :
720 : // Show frame borders when rendering
721 : static void ShowFrameBorders(bool aEnable);
722 : static bool GetShowFrameBorders();
723 :
724 : // Show frame border of event target
725 : static void ShowEventTargetFrameBorder(bool aEnable);
726 : static bool GetShowEventTargetFrameBorder();
727 :
728 : #endif
729 : #ifdef MOZ_DUMP_PAINTING
730 : public:
731 :
732 : static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
733 : const nsDisplayList& aList,
734 : FILE* aFile = stdout);
735 :
736 : #endif
737 : };
738 :
739 : // Start Display Reflow Debugging
740 : #ifdef DEBUG
741 :
742 : struct DR_cookie {
743 : DR_cookie(nsPresContext* aPresContext,
744 : nsIFrame* aFrame,
745 : const nsHTMLReflowState& aReflowState,
746 : nsHTMLReflowMetrics& aMetrics,
747 : nsReflowStatus& aStatus);
748 : ~DR_cookie();
749 : void Change() const;
750 :
751 : nsPresContext* mPresContext;
752 : nsIFrame* mFrame;
753 : const nsHTMLReflowState& mReflowState;
754 : nsHTMLReflowMetrics& mMetrics;
755 : nsReflowStatus& mStatus;
756 : void* mValue;
757 : };
758 :
759 : struct DR_layout_cookie {
760 : DR_layout_cookie(nsIFrame* aFrame);
761 : ~DR_layout_cookie();
762 :
763 : nsIFrame* mFrame;
764 : void* mValue;
765 : };
766 :
767 : struct DR_intrinsic_width_cookie {
768 : DR_intrinsic_width_cookie(nsIFrame* aFrame, const char* aType,
769 : nscoord& aResult);
770 : ~DR_intrinsic_width_cookie();
771 :
772 : nsIFrame* mFrame;
773 : const char* mType;
774 : nscoord& mResult;
775 : void* mValue;
776 : };
777 :
778 : struct DR_intrinsic_size_cookie {
779 : DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
780 : nsSize& aResult);
781 : ~DR_intrinsic_size_cookie();
782 :
783 : nsIFrame* mFrame;
784 : const char* mType;
785 : nsSize& mResult;
786 : void* mValue;
787 : };
788 :
789 : struct DR_init_constraints_cookie {
790 : DR_init_constraints_cookie(nsIFrame* aFrame, nsHTMLReflowState* aState,
791 : nscoord aCBWidth, nscoord aCBHeight,
792 : const nsMargin* aBorder,
793 : const nsMargin* aPadding);
794 : ~DR_init_constraints_cookie();
795 :
796 : nsIFrame* mFrame;
797 : nsHTMLReflowState* mState;
798 : void* mValue;
799 : };
800 :
801 : struct DR_init_offsets_cookie {
802 : DR_init_offsets_cookie(nsIFrame* aFrame, nsCSSOffsetState* aState,
803 : nscoord aCBWidth, const nsMargin* aBorder,
804 : const nsMargin* aPadding);
805 : ~DR_init_offsets_cookie();
806 :
807 : nsIFrame* mFrame;
808 : nsCSSOffsetState* mState;
809 : void* mValue;
810 : };
811 :
812 : struct DR_init_type_cookie {
813 : DR_init_type_cookie(nsIFrame* aFrame, nsHTMLReflowState* aState);
814 : ~DR_init_type_cookie();
815 :
816 : nsIFrame* mFrame;
817 : nsHTMLReflowState* mState;
818 : void* mValue;
819 : };
820 :
821 : #define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status) \
822 : DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status);
823 : #define DISPLAY_REFLOW_CHANGE() \
824 : dr_cookie.Change();
825 : #define DISPLAY_LAYOUT(dr_frame) \
826 : DR_layout_cookie dr_cookie(dr_frame);
827 : #define DISPLAY_MIN_WIDTH(dr_frame, dr_result) \
828 : DR_intrinsic_width_cookie dr_cookie(dr_frame, "Min", dr_result)
829 : #define DISPLAY_PREF_WIDTH(dr_frame, dr_result) \
830 : DR_intrinsic_width_cookie dr_cookie(dr_frame, "Pref", dr_result)
831 : #define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
832 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
833 : #define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
834 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
835 : #define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
836 : DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
837 : #define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, \
838 : dr_bdr, dr_pad) \
839 : DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \
840 : dr_bdr, dr_pad)
841 : #define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad) \
842 : DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad)
843 : #define DISPLAY_INIT_TYPE(dr_frame, dr_result) \
844 : DR_init_type_cookie dr_cookie(dr_frame, dr_result)
845 :
846 : #else
847 :
848 : #define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status)
849 : #define DISPLAY_REFLOW_CHANGE()
850 : #define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
851 : #define DISPLAY_MIN_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
852 : #define DISPLAY_PREF_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
853 : #define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
854 : #define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
855 : #define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
856 : #define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, \
857 : dr_bdr, dr_pad) \
858 : PR_BEGIN_MACRO PR_END_MACRO
859 : #define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_cbw, dr_bdr, dr_pad) \
860 : PR_BEGIN_MACRO PR_END_MACRO
861 : #define DISPLAY_INIT_TYPE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
862 :
863 : #endif
864 : // End Display Reflow Debugging
865 :
866 : // similar to NS_ENSURE_TRUE but with no return value
867 : #define ENSURE_TRUE(x) \
868 : PR_BEGIN_MACRO \
869 : if (!(x)) { \
870 : NS_WARNING("ENSURE_TRUE(" #x ") failed"); \
871 : return; \
872 : } \
873 : PR_END_MACRO
874 : #endif /* nsFrame_h___ */
|