1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim:cindent:ts=2:et:sw=2:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Netscape Communications Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 1998
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Steve Clark <buster@netscape.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK *****
40 : * This Original Code has been modified by IBM Corporation. Modifications made by IBM
41 : * described herein are Copyright (c) International Business Machines Corporation, 2000.
42 : * Modifications to Mozilla code or documentation identified per MPL Section 3.3
43 : *
44 : * Date Modified by Description of modification
45 : * 04/20/2000 IBM Corp. OS/2 VisualAge build.
46 : */
47 :
48 : /* state and methods used while laying out a single line of a block frame */
49 :
50 : #ifndef nsLineLayout_h___
51 : #define nsLineLayout_h___
52 :
53 : #include "nsFrame.h"
54 : #include "nsDeque.h"
55 : #include "nsLineBox.h"
56 : #include "nsBlockReflowState.h"
57 : #include "plarena.h"
58 : #include "gfxTypes.h"
59 :
60 : class nsBlockFrame;
61 :
62 : class nsFloatManager;
63 : class nsPlaceholderFrame;
64 : struct nsStyleText;
65 :
66 : class nsLineLayout {
67 : public:
68 : nsLineLayout(nsPresContext* aPresContext,
69 : nsFloatManager* aFloatManager,
70 : const nsHTMLReflowState* aOuterReflowState,
71 : const nsLineList::iterator* aLine);
72 : ~nsLineLayout();
73 :
74 0 : void Init(nsBlockReflowState* aState, nscoord aMinLineHeight,
75 : PRInt32 aLineNumber) {
76 0 : mBlockRS = aState;
77 0 : mMinLineHeight = aMinLineHeight;
78 0 : mLineNumber = aLineNumber;
79 0 : }
80 :
81 0 : PRInt32 GetLineNumber() const {
82 0 : return mLineNumber;
83 : }
84 :
85 : void BeginLineReflow(nscoord aX, nscoord aY,
86 : nscoord aWidth, nscoord aHeight,
87 : bool aImpactedByFloats,
88 : bool aIsTopOfPage,
89 : PRUint8 aDirection);
90 :
91 : void EndLineReflow();
92 :
93 : /**
94 : * Called when a float has been placed. This method updates the
95 : * inline frame and span data to account for any change in positions
96 : * due to available space for the line boxes changing.
97 : * @param aX/aY/aWidth/aHeight are the new available
98 : * space rectangle, relative to the containing block.
99 : * @param aFloatFrame the float frame that was placed.
100 : */
101 : void UpdateBand(const nsRect& aNewAvailableSpace,
102 : nsIFrame* aFloatFrame);
103 :
104 : nsresult BeginSpan(nsIFrame* aFrame,
105 : const nsHTMLReflowState* aSpanReflowState,
106 : nscoord aLeftEdge,
107 : nscoord aRightEdge,
108 : nscoord* aBaseline);
109 :
110 : // Returns the width of the span
111 : nscoord EndSpan(nsIFrame* aFrame);
112 :
113 : PRInt32 GetCurrentSpanCount() const;
114 :
115 : void SplitLineTo(PRInt32 aNewCount);
116 :
117 : bool IsZeroHeight();
118 :
119 : // Reflows the frame and returns the reflow status. aPushedFrame is true
120 : // if the frame is pushed to the next line because it doesn't fit
121 : nsresult ReflowFrame(nsIFrame* aFrame,
122 : nsReflowStatus& aReflowStatus,
123 : nsHTMLReflowMetrics* aMetrics,
124 : bool& aPushedFrame);
125 :
126 : nsresult AddBulletFrame(nsIFrame* aFrame,
127 : const nsHTMLReflowMetrics& aMetrics);
128 :
129 0 : void RemoveBulletFrame(nsIFrame* aFrame) {
130 0 : PushFrame(aFrame);
131 0 : }
132 :
133 : void VerticalAlignLine();
134 :
135 : bool TrimTrailingWhiteSpace();
136 :
137 : void HorizontalAlignFrames(nsRect& aLineBounds, bool aIsLastLine);
138 :
139 : /**
140 : * Handle all the relative positioning in the line, compute the
141 : * combined area (== overflow area) for the line, and handle view
142 : * sizing/positioning and the setting of the overflow rect.
143 : */
144 : void RelativePositionFrames(nsOverflowAreas& aOverflowAreas);
145 :
146 : //----------------------------------------
147 :
148 : // Supporting methods and data for flags
149 : protected:
150 : #define LL_FIRSTLETTERSTYLEOK 0x00000008
151 : #define LL_ISTOPOFPAGE 0x00000010
152 : #define LL_IMPACTEDBYFLOATS 0x00000040
153 : #define LL_LASTFLOATWASLETTERFRAME 0x00000080
154 : #define LL_LINEISEMPTY 0x00000100
155 : #define LL_LINEENDSINBR 0x00000200
156 : #define LL_NEEDBACKUP 0x00000400
157 : #define LL_INFIRSTLINE 0x00000800
158 : #define LL_GOTLINEBOX 0x00001000
159 : #define LL_INFIRSTLETTER 0x00002000
160 : #define LL_HASBULLET 0x00004000
161 : #define LL_DIRTYNEXTLINE 0x00008000
162 : #define LL_LINEATSTART 0x00010000
163 : #define LL_LASTFLAG LL_LINEATSTART
164 :
165 0 : void SetFlag(PRUint32 aFlag, bool aValue)
166 : {
167 0 : NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
168 : NS_ASSERTION(aValue==false || aValue==true, "bad value");
169 0 : if (aValue) { // set flag
170 0 : mFlags |= aFlag;
171 : }
172 : else { // unset flag
173 0 : mFlags &= ~aFlag;
174 : }
175 0 : }
176 :
177 0 : bool GetFlag(PRUint32 aFlag) const
178 : {
179 0 : NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
180 0 : return !!(mFlags & aFlag);
181 : }
182 :
183 : public:
184 :
185 : // Support methods for word-wrapping during line reflow
186 :
187 0 : void SetTextJustificationWeights(PRInt32 aNumSpaces, PRInt32 aNumLetters) {
188 0 : mTextJustificationNumSpaces = aNumSpaces;
189 0 : mTextJustificationNumLetters = aNumLetters;
190 0 : }
191 :
192 : /**
193 : * @return true if so far during reflow no non-empty content has been
194 : * placed in the line (according to nsIFrame::IsEmpty())
195 : */
196 0 : bool LineIsEmpty() const
197 : {
198 0 : return GetFlag(LL_LINEISEMPTY);
199 : }
200 :
201 : /**
202 : * @return true if so far during reflow no non-empty leaf content
203 : * (non-collapsed whitespace, replaced element, inline-block, etc) has been
204 : * placed in the line
205 : */
206 0 : bool LineAtStart() const
207 : {
208 0 : return GetFlag(LL_LINEATSTART);
209 : }
210 :
211 : bool LineIsBreakable() const;
212 :
213 0 : bool GetLineEndsInBR() const
214 : {
215 0 : return GetFlag(LL_LINEENDSINBR);
216 : }
217 :
218 0 : void SetLineEndsInBR(bool aOn)
219 : {
220 0 : SetFlag(LL_LINEENDSINBR, aOn);
221 0 : }
222 :
223 : //----------------------------------------
224 : // Inform the line-layout about the presence of a floating frame
225 : // XXX get rid of this: use get-frame-type?
226 0 : bool AddFloat(nsIFrame* aFloat, nscoord aAvailableWidth)
227 : {
228 0 : return mBlockRS->AddFloat(this, aFloat, aAvailableWidth);
229 : }
230 :
231 0 : void SetTrimmableWidth(nscoord aTrimmableWidth) {
232 0 : mTrimmableWidth = aTrimmableWidth;
233 0 : }
234 :
235 : //----------------------------------------
236 :
237 0 : bool GetFirstLetterStyleOK() const {
238 0 : return GetFlag(LL_FIRSTLETTERSTYLEOK);
239 : }
240 :
241 0 : void SetFirstLetterStyleOK(bool aSetting) {
242 0 : SetFlag(LL_FIRSTLETTERSTYLEOK, aSetting);
243 0 : }
244 :
245 0 : bool GetInFirstLetter() const {
246 0 : return GetFlag(LL_INFIRSTLETTER);
247 : }
248 :
249 0 : void SetInFirstLetter(bool aSetting) {
250 0 : SetFlag(LL_INFIRSTLETTER, aSetting);
251 0 : }
252 :
253 0 : bool GetInFirstLine() const {
254 0 : return GetFlag(LL_INFIRSTLINE);
255 : }
256 :
257 0 : void SetInFirstLine(bool aSetting) {
258 0 : SetFlag(LL_INFIRSTLINE, aSetting);
259 0 : }
260 :
261 : // Calling this during block reflow ensures that the next line of inlines
262 : // will be marked dirty, if there is one.
263 0 : void SetDirtyNextLine() {
264 0 : SetFlag(LL_DIRTYNEXTLINE, true);
265 0 : }
266 0 : bool GetDirtyNextLine() {
267 0 : return GetFlag(LL_DIRTYNEXTLINE);
268 : }
269 :
270 : //----------------------------------------
271 :
272 : nsPresContext* mPresContext;
273 :
274 : /**
275 : * Record where an optional break could have been placed. During line reflow,
276 : * frames containing optional break points (e.g., whitespace in text frames)
277 : * can call SetLastOptionalBreakPosition to record where a break could
278 : * have been made, but wasn't because we decided to place more content on
279 : * the line. For non-text frames, offset 0 means
280 : * before the content, offset PR_INT32_MAX means after the content.
281 : *
282 : * Currently this is used to handle cases where a single word comprises
283 : * multiple frames, and the first frame fits on the line but the whole word
284 : * doesn't. We look back to the last optional break position and
285 : * reflow the whole line again, forcing a break at that position. The last
286 : * optional break position could be in a text frame or else after a frame
287 : * that cannot be part of a text run, so those are the positions we record.
288 : *
289 : * @param aFits set to true if the break position is within the available width.
290 : *
291 : * @param aPriority the priority of the break opportunity. If we are
292 : * prioritizing break opportunities, we will not set a break if we have
293 : * already set a break with a higher priority. @see gfxBreakPriority.
294 : *
295 : * @return true if we are actually reflowing with forced break position and we
296 : * should break here
297 : */
298 0 : bool NotifyOptionalBreakPosition(nsIContent* aContent, PRInt32 aOffset,
299 : bool aFits, gfxBreakPriority aPriority) {
300 0 : NS_ASSERTION(!aFits || !GetFlag(LL_NEEDBACKUP),
301 : "Shouldn't be updating the break position with a break that fits after we've already flagged an overrun");
302 : // Remember the last break position that fits; if there was no break that fit,
303 : // just remember the first break
304 0 : if ((aFits && aPriority >= mLastOptionalBreakPriority) ||
305 0 : !mLastOptionalBreakContent) {
306 0 : mLastOptionalBreakContent = aContent;
307 0 : mLastOptionalBreakContentOffset = aOffset;
308 0 : mLastOptionalBreakPriority = aPriority;
309 : }
310 : return aContent && mForceBreakContent == aContent &&
311 0 : mForceBreakContentOffset == aOffset;
312 : }
313 : /**
314 : * Like NotifyOptionalBreakPosition, but here it's OK for LL_NEEDBACKUP
315 : * to be set, because the caller is merely pruning some saved break position(s)
316 : * that are actually not feasible.
317 : */
318 0 : void RestoreSavedBreakPosition(nsIContent* aContent, PRInt32 aOffset,
319 : gfxBreakPriority aPriority) {
320 0 : mLastOptionalBreakContent = aContent;
321 0 : mLastOptionalBreakContentOffset = aOffset;
322 0 : mLastOptionalBreakPriority = aPriority;
323 0 : }
324 : /**
325 : * Signal that no backing up will be required after all.
326 : */
327 0 : void ClearOptionalBreakPosition() {
328 0 : SetFlag(LL_NEEDBACKUP, false);
329 0 : mLastOptionalBreakContent = nsnull;
330 0 : mLastOptionalBreakContentOffset = -1;
331 0 : mLastOptionalBreakPriority = eNoBreak;
332 0 : }
333 : // Retrieve last set optional break position. When this returns null, no
334 : // optional break has been recorded (which means that the line can't break yet).
335 0 : nsIContent* GetLastOptionalBreakPosition(PRInt32* aOffset,
336 : gfxBreakPriority* aPriority) {
337 0 : *aOffset = mLastOptionalBreakContentOffset;
338 0 : *aPriority = mLastOptionalBreakPriority;
339 0 : return mLastOptionalBreakContent;
340 : }
341 :
342 : /**
343 : * Check whether frames overflowed the available width and CanPlaceFrame
344 : * requested backing up to a saved break position.
345 : */
346 0 : bool NeedsBackup() { return GetFlag(LL_NEEDBACKUP); }
347 :
348 : // Line layout may place too much content on a line, overflowing its available
349 : // width. When that happens, if SetLastOptionalBreakPosition has been
350 : // used to record an optional break that wasn't taken, we can reflow the line
351 : // again and force the break to happen at that point (i.e., backtracking
352 : // to the last choice point).
353 :
354 : // Record that we want to break at the given content+offset (which
355 : // should have been previously returned by GetLastOptionalBreakPosition
356 : // from another nsLineLayout).
357 0 : void ForceBreakAtPosition(nsIContent* aContent, PRInt32 aOffset) {
358 0 : mForceBreakContent = aContent;
359 0 : mForceBreakContentOffset = aOffset;
360 0 : }
361 0 : bool HaveForcedBreakPosition() { return mForceBreakContent != nsnull; }
362 0 : PRInt32 GetForcedBreakPosition(nsIContent* aContent) {
363 0 : return mForceBreakContent == aContent ? mForceBreakContentOffset : -1;
364 : }
365 :
366 : /**
367 : * This can't be null. It usually returns a block frame but may return
368 : * some other kind of frame when inline frames are reflowed in a non-block
369 : * context (e.g. MathML or floating first-letter).
370 : */
371 0 : nsIFrame* GetLineContainerFrame() const { return mBlockReflowState->frame; }
372 0 : const nsHTMLReflowState* GetLineContainerRS() const {
373 0 : return mBlockReflowState;
374 : }
375 : const nsLineList::iterator* GetLine() const {
376 : return GetFlag(LL_GOTLINEBOX) ? &mLineBox : nsnull;
377 : }
378 0 : nsLineList::iterator* GetLine() {
379 0 : return GetFlag(LL_GOTLINEBOX) ? &mLineBox : nsnull;
380 : }
381 :
382 : /**
383 : * Returns the accumulated advance width of frames before the current frame
384 : * on the line, plus the line container's left border+padding.
385 : * This is always positive, the advance width is measured from
386 : * the right edge for RTL blocks and from the left edge for LTR blocks.
387 : * In other words, the current frame's distance from the line container's
388 : * start content edge is:
389 : * <code>GetCurrentFrameXDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left</code>
390 : * Note the use of <code>.left</code> for both LTR and RTL line containers.
391 : */
392 : nscoord GetCurrentFrameXDistanceFromBlock();
393 :
394 : protected:
395 : // This state is constant for a given block frame doing line layout
396 : nsFloatManager* mFloatManager;
397 : const nsStyleText* mStyleText; // for the block
398 : const nsHTMLReflowState* mBlockReflowState;
399 :
400 : nsIContent* mLastOptionalBreakContent;
401 : nsIContent* mForceBreakContent;
402 :
403 : // XXX remove this when landing bug 154892 (splitting absolute positioned frames)
404 : friend class nsInlineFrame;
405 :
406 : nsBlockReflowState* mBlockRS;/* XXX hack! */
407 :
408 : nsLineList::iterator mLineBox;
409 :
410 : // Per-frame data recorded by the line-layout reflow logic. This
411 : // state is the state needed to post-process the line after reflow
412 : // has completed (vertical alignment, horizontal alignment,
413 : // justification and relative positioning).
414 :
415 : struct PerSpanData;
416 : struct PerFrameData;
417 : friend struct PerSpanData;
418 : friend struct PerFrameData;
419 0 : struct PerFrameData {
420 : // link to next/prev frame in same span
421 : PerFrameData* mNext;
422 : PerFrameData* mPrev;
423 :
424 : // pointer to child span data if this is an inline container frame
425 : PerSpanData* mSpan;
426 :
427 : // The frame
428 : nsIFrame* mFrame;
429 :
430 : // From metrics
431 : nscoord mAscent;
432 : nsRect mBounds;
433 : nsOverflowAreas mOverflowAreas;
434 :
435 : // From reflow-state
436 : nsMargin mMargin;
437 : nsMargin mBorderPadding;
438 : nsMargin mOffsets;
439 :
440 : // state for text justification
441 : PRInt32 mJustificationNumSpaces;
442 : PRInt32 mJustificationNumLetters;
443 :
444 : // Other state we use
445 : PRUint8 mVerticalAlign;
446 :
447 : // PerFrameData flags
448 : #define PFD_RELATIVEPOS 0x00000001
449 : #define PFD_ISTEXTFRAME 0x00000002
450 : #define PFD_ISNONEMPTYTEXTFRAME 0x00000004
451 : #define PFD_ISNONWHITESPACETEXTFRAME 0x00000008
452 : #define PFD_ISLETTERFRAME 0x00000010
453 : #define PFD_RECOMPUTEOVERFLOW 0x00000020
454 : #define PFD_ISBULLET 0x00000040
455 : #define PFD_SKIPWHENTRIMMINGWHITESPACE 0x00000080
456 : #define PFD_LASTFLAG PFD_SKIPWHENTRIMMINGWHITESPACE
457 :
458 : PRUint8 mFlags;
459 :
460 0 : void SetFlag(PRUint32 aFlag, bool aValue)
461 : {
462 0 : NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
463 0 : NS_ASSERTION(aFlag<=PR_UINT8_MAX, "bad flag");
464 : NS_ASSERTION(aValue==false || aValue==true, "bad value");
465 0 : if (aValue) { // set flag
466 0 : mFlags |= aFlag;
467 : }
468 : else { // unset flag
469 0 : mFlags &= ~aFlag;
470 : }
471 0 : }
472 :
473 0 : bool GetFlag(PRUint32 aFlag) const
474 : {
475 0 : NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
476 0 : return !!(mFlags & aFlag);
477 : }
478 :
479 :
480 0 : PerFrameData* Last() {
481 0 : PerFrameData* pfd = this;
482 0 : while (pfd->mNext) {
483 0 : pfd = pfd->mNext;
484 : }
485 0 : return pfd;
486 : }
487 : };
488 : PerFrameData* mFrameFreeList;
489 :
490 : struct PerSpanData {
491 : union {
492 : PerSpanData* mParent;
493 : PerSpanData* mNextFreeSpan;
494 : };
495 : PerFrameData* mFrame;
496 : PerFrameData* mFirstFrame;
497 : PerFrameData* mLastFrame;
498 :
499 : const nsHTMLReflowState* mReflowState;
500 : bool mNoWrap;
501 : PRUint8 mDirection;
502 : bool mChangedFrameDirection;
503 : bool mZeroEffectiveSpanBox;
504 : bool mContainsFloat;
505 : bool mHasNonemptyContent;
506 :
507 : nscoord mLeftEdge;
508 : nscoord mX;
509 : nscoord mRightEdge;
510 :
511 : nscoord mTopLeading, mBottomLeading;
512 : nscoord mLogicalHeight;
513 : nscoord mMinY, mMaxY;
514 : nscoord* mBaseline;
515 :
516 0 : void AppendFrame(PerFrameData* pfd) {
517 0 : if (nsnull == mLastFrame) {
518 0 : mFirstFrame = pfd;
519 : }
520 : else {
521 0 : mLastFrame->mNext = pfd;
522 0 : pfd->mPrev = mLastFrame;
523 : }
524 0 : mLastFrame = pfd;
525 0 : }
526 : };
527 : PerSpanData* mSpanFreeList;
528 : PerSpanData* mRootSpan;
529 : PerSpanData* mCurrentSpan;
530 :
531 : gfxBreakPriority mLastOptionalBreakPriority;
532 : PRInt32 mLastOptionalBreakContentOffset;
533 : PRInt32 mForceBreakContentOffset;
534 :
535 : nscoord mMinLineHeight;
536 :
537 : // The amount of text indent that we applied to this line, needed for
538 : // max-element-size calculation.
539 : nscoord mTextIndent;
540 :
541 : // This state varies during the reflow of a line but is line
542 : // "global" state not span "local" state.
543 : PRInt32 mLineNumber;
544 : PRInt32 mTextJustificationNumSpaces;
545 : PRInt32 mTextJustificationNumLetters;
546 :
547 : PRInt32 mTotalPlacedFrames;
548 :
549 : nscoord mTopEdge;
550 : nscoord mMaxTopBoxHeight;
551 : nscoord mMaxBottomBoxHeight;
552 :
553 : nscoord mInflationMinFontSize;
554 :
555 : // Final computed line-height value after VerticalAlignFrames for
556 : // the block has been called.
557 : nscoord mFinalLineHeight;
558 :
559 : // Amount of trimmable whitespace width for the trailing text frame, if any
560 : nscoord mTrimmableWidth;
561 :
562 : PRInt32 mSpanDepth;
563 : #ifdef DEBUG
564 : PRInt32 mSpansAllocated, mSpansFreed;
565 : PRInt32 mFramesAllocated, mFramesFreed;
566 : #endif
567 : PLArenaPool mArena; // Per span and per frame data, 4 byte aligned
568 :
569 : PRUint32 mFlags;
570 :
571 : nsresult NewPerFrameData(PerFrameData** aResult);
572 :
573 : nsresult NewPerSpanData(PerSpanData** aResult);
574 :
575 : void FreeSpan(PerSpanData* psd);
576 :
577 : bool InBlockContext() const {
578 : return mSpanDepth == 0;
579 : }
580 :
581 : void PushFrame(nsIFrame* aFrame);
582 :
583 : void ApplyStartMargin(PerFrameData* pfd,
584 : nsHTMLReflowState& aReflowState);
585 :
586 : bool CanPlaceFrame(PerFrameData* pfd,
587 : PRUint8 aFrameDirection,
588 : bool aNotSafeToBreak,
589 : bool aFrameCanContinueTextRun,
590 : bool aCanRollBackBeforeFrame,
591 : nsHTMLReflowMetrics& aMetrics,
592 : nsReflowStatus& aStatus,
593 : bool* aOptionalBreakAfterFits);
594 :
595 : void PlaceFrame(PerFrameData* pfd,
596 : nsHTMLReflowMetrics& aMetrics);
597 :
598 : void VerticalAlignFrames(PerSpanData* psd);
599 :
600 : void PlaceTopBottomFrames(PerSpanData* psd,
601 : nscoord aDistanceFromTop,
602 : nscoord aLineHeight);
603 :
604 : void RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflowAreas);
605 :
606 : bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
607 :
608 : void ComputeJustificationWeights(PerSpanData* psd, PRInt32* numSpaces, PRInt32* numLetters);
609 :
610 : struct FrameJustificationState {
611 : PRInt32 mTotalNumSpaces;
612 : PRInt32 mTotalNumLetters;
613 : nscoord mTotalWidthForSpaces;
614 : nscoord mTotalWidthForLetters;
615 : PRInt32 mNumSpacesProcessed;
616 : PRInt32 mNumLettersProcessed;
617 : nscoord mWidthForSpacesProcessed;
618 : nscoord mWidthForLettersProcessed;
619 : };
620 :
621 : // Apply justification. The return value is the amount by which the width of
622 : // the span corresponding to aPSD got increased due to justification.
623 : nscoord ApplyFrameJustification(PerSpanData* aPSD,
624 : FrameJustificationState* aState);
625 :
626 :
627 : #ifdef DEBUG
628 : void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
629 : #endif
630 : };
631 :
632 : #endif /* nsLineLayout_h___ */
|