layout/doc/DD-SpaceManager.html

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

michael@0 1 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 4
michael@0 5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
michael@0 6 <html>
michael@0 7 <head>
michael@0 8
michael@0 9 <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
michael@0 10 <title>Detailed Design Template</title>
michael@0 11 </head>
michael@0 12 <body>
michael@0 13
michael@0 14 <h1><font color="#cc0000">Gecko Layout Detailed Design Document</font></h1>
michael@0 15
michael@0 16 <h1>Space Manager Detailed Design</h1>
michael@0 17
michael@0 18 <h2>Overview</h2>
michael@0 19 <p>
michael@0 20 The Space Manager and related classes and structures are an important of
michael@0 21 the Gecko Layout system, specifically Block Layout. &nbsp;See the High Level
michael@0 22 Design document for an overview of the Space Manager, and as an introduction
michael@0 23 to the classes, structures and algorithms container in this, the Detailed
michael@0 24 Design Document.
michael@0 25 </p>
michael@0 26
michael@0 27
michael@0 28
michael@0 29 <hr width="100%" size="2">
michael@0 30 <h2>nsSpaceManager</h2>
michael@0 31 <p>
michael@0 32 The Space Manager is the central class is a group of classes that manage
michael@0 33 the occupied and available space that exists in horizontal bands across
michael@0 34 a canvas. &nbsp;The primary goal of the Space Manager is to provide information
michael@0 35 about those bands of space to support the CSS notion of floated elements.
michael@0 36 </p>
michael@0 37
michael@0 38 <p>
michael@0 39 There are three important parts to the Space Manager API: the parts that
michael@0 40 deal with the coordinate space of the Space Manager, the parts that deal with
michael@0 41 the regions managed by the Space Manager, and the parts that manage float
michael@0 42 impact intervals.
michael@0 43 </p>
michael@0 44
michael@0 45 <p>
michael@0 46 The class nsSpaceManager is declared in the file <a href="http://lxr.mozilla.org/seamonkey/source/layout/base/src/nsSpaceManager.h">
michael@0 47 nsSpaceManger.h</a>
michael@0 48 . &nbsp;The class is only used in the layout module and cannot be exported
michael@0 49 outside of that module (nor does it need to be). &nbsp;It is not a general
michael@0 50 purpose class, and is not intended to be subclasses<font color="#cc0000">
michael@0 51 .</font>
michael@0 52 </p>
michael@0 53
michael@0 54 <p>
michael@0 55 Here is the class declaration, taken from the source file as of 01.08.02
michael@0 56 </p>
michael@0 57
michael@0 58
michael@0 59
michael@0 60 <pre>/**
michael@0 61 * Class for dealing with bands of available space. The space manager
michael@0 62 * defines a coordinate space with an origin at (0, 0) that grows down
michael@0 63 * and to the right.
michael@0 64 */
michael@0 65 class nsSpaceManager {
michael@0 66 public:
michael@0 67 nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
michael@0 68 ~nsSpaceManager();
michael@0 69
michael@0 70 void* operator new(size_t aSize);
michael@0 71 void operator delete(void* aPtr, size_t aSize);
michael@0 72
michael@0 73 static void Shutdown();
michael@0 74
michael@0 75 /*
michael@0 76 * Get the frame that's associated with the space manager. This frame
michael@0 77 * created the space manager, and the world coordinate space is
michael@0 78 * relative to this frame.
michael@0 79 *
michael@0 80 * You can use QueryInterface() on this frame to get any additional
michael@0 81 * interfaces.
michael@0 82 */
michael@0 83 nsIFrame* GetFrame() const { return mFrame; }
michael@0 84
michael@0 85 /**
michael@0 86 * Translate the current origin by the specified (dx, dy). This
michael@0 87 * creates a new local coordinate space relative to the current
michael@0 88 * coordinate space.
michael@0 89 */
michael@0 90 void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
michael@0 91
michael@0 92 /**
michael@0 93 * Returns the current translation from local coordinate space to
michael@0 94 * world coordinate space. This represents the accumulated calls to
michael@0 95 * Translate().
michael@0 96 */
michael@0 97 void GetTranslation(nscoord&amp; aX, nscoord&amp; aY) const { aX = mX; aY = mY; }
michael@0 98
michael@0 99 /**
michael@0 100 * Returns the y-most of the bottommost band or 0 if there are no bands.
michael@0 101 *
michael@0 102 * @return PR_TRUE if there are bands and PR_FALSE if there are no bands
michael@0 103 */
michael@0 104 PRBool YMost(nscoord&amp; aYMost) const;
michael@0 105
michael@0 106 /**
michael@0 107 * Returns a band starting at the specified y-offset. The band data
michael@0 108 * indicates which parts of the band are available, and which parts
michael@0 109 * are unavailable
michael@0 110 *
michael@0 111 * The band data that is returned is in the coordinate space of the
michael@0 112 * local coordinate system.
michael@0 113 *
michael@0 114 * The local coordinate space origin, the y-offset, and the max size
michael@0 115 * describe a rectangle that's used to clip the underlying band of
michael@0 116 * available space, i.e.
michael@0 117 * {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
michael@0 118 * coordinate space
michael@0 119 *
michael@0 120 * @param aYOffset the y-offset of where the band begins. The coordinate is
michael@0 121 * relative to the upper-left corner of the local coordinate space
michael@0 122 * @param aMaxSize the size to use to constrain the band data
michael@0 123 * @param aBandData [in,out] used to return the list of trapezoids that
michael@0 124 * describe the available space and the unavailable space
michael@0 125 * @return NS_OK if successful and NS_ERROR_FAILURE if the band data is not
michael@0 126 * not large enough. The 'count' member of the band data struct
michael@0 127 * indicates how large the array of trapezoids needs to be
michael@0 128 */
michael@0 129 nsresult GetBandData(nscoord aYOffset,
michael@0 130 const nsSize&amp; aMaxSize,
michael@0 131 nsBandData&amp; aBandData) const;
michael@0 132
michael@0 133 /**
michael@0 134 * Add a rectangular region of unavailable space. The space is
michael@0 135 * relative to the local coordinate system.
michael@0 136 *
michael@0 137 * The region is tagged with a frame
michael@0 138 *
michael@0 139 * @param aFrame the frame used to identify the region. Must not be NULL
michael@0 140 * @param aUnavailableSpace the bounding rect of the unavailable space
michael@0 141 * @return NS_OK if successful
michael@0 142 * NS_ERROR_FAILURE if there is already a region tagged with aFrame
michael@0 143 */
michael@0 144 nsresult AddRectRegion(nsIFrame* aFrame,
michael@0 145 const nsRect&amp; aUnavailableSpace);
michael@0 146
michael@0 147 /**
michael@0 148 * Resize the rectangular region associated with aFrame by the specified
michael@0 149 * deltas. The height change always applies to the bottom edge or the existing
michael@0 150 * rect. You specify whether the width change applies to the left or right edge
michael@0 151 *
michael@0 152 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
michael@0 153 * tagged with aFrame
michael@0 154 */
michael@0 155 enum AffectedEdge {LeftEdge, RightEdge};
michael@0 156 nsresult ResizeRectRegion(nsIFrame* aFrame,
michael@0 157 nscoord aDeltaWidth,
michael@0 158 nscoord aDeltaHeight,
michael@0 159 AffectedEdge aEdge = RightEdge);
michael@0 160
michael@0 161 /**
michael@0 162 * Offset the region associated with aFrame by the specified amount.
michael@0 163 *
michael@0 164 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
michael@0 165 * tagged with aFrame
michael@0 166 */
michael@0 167 nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);
michael@0 168
michael@0 169 /**
michael@0 170 * Remove the region associated with aFrane.
michael@0 171 *
michael@0 172 * Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
michael@0 173 * tagged with aFrame
michael@0 174 */
michael@0 175 nsresult RemoveRegion(nsIFrame* aFrame);
michael@0 176
michael@0 177 /**
michael@0 178 * Clears the list of regions representing the unavailable space.
michael@0 179 */
michael@0 180 void ClearRegions();
michael@0 181
michael@0 182 /**
michael@0 183 * Methods for dealing with the propagation of float damage during
michael@0 184 * reflow.
michael@0 185 */
michael@0 186 PRBool HasFloatDamage()
michael@0 187 {
michael@0 188 return !mFloatDamage.IsEmpty();
michael@0 189 }
michael@0 190
michael@0 191 void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
michael@0 192 {
michael@0 193 mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
michael@0 194 }
michael@0 195
michael@0 196 PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
michael@0 197 {
michael@0 198 return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
michael@0 199 }
michael@0 200
michael@0 201 #ifdef DEBUG
michael@0 202 /**
michael@0 203 * Dump the state of the spacemanager out to a file
michael@0 204 */
michael@0 205 nsresult List(FILE* out);
michael@0 206
michael@0 207 void SizeOf(nsISizeOfHandler* aHandler, uint32_t* aResult) const;
michael@0 208 #endif
michael@0 209
michael@0 210 private:
michael@0 211 // Structure that maintains information about the region associated
michael@0 212 // with a particular frame
michael@0 213 struct FrameInfo {
michael@0 214 nsIFrame* const mFrame;
michael@0 215 nsRect mRect; // rectangular region
michael@0 216 FrameInfo* mNext;
michael@0 217
michael@0 218 FrameInfo(nsIFrame* aFrame, const nsRect&amp; aRect);
michael@0 219 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 220 ~FrameInfo();
michael@0 221 #endif
michael@0 222 };
michael@0 223
michael@0 224 // Doubly linked list of band rects
michael@0 225 struct BandRect : PRCListStr {
michael@0 226 nscoord mLeft, mTop;
michael@0 227 nscoord mRight, mBottom;
michael@0 228 int32_t mNumFrames; // number of frames occupying this rect
michael@0 229 union {
michael@0 230 nsIFrame* mFrame; // single frame occupying the space
michael@0 231 nsVoidArray* mFrames; // list of frames occupying the space
michael@0 232 };
michael@0 233
michael@0 234 BandRect(nscoord aLeft, nscoord aTop,
michael@0 235 nscoord aRight, nscoord aBottom,
michael@0 236 nsIFrame*);
michael@0 237 BandRect(nscoord aLeft, nscoord aTop,
michael@0 238 nscoord aRight, nscoord aBottom,
michael@0 239 nsVoidArray*);
michael@0 240 ~BandRect();
michael@0 241
michael@0 242 // List operations
michael@0 243 BandRect* Next() const {return (BandRect*)PR_NEXT_LINK(this);}
michael@0 244 BandRect* Prev() const {return (BandRect*)PR_PREV_LINK(this);}
michael@0 245 void InsertBefore(BandRect* aBandRect) {PR_INSERT_BEFORE(aBandRect, this);}
michael@0 246 void InsertAfter(BandRect* aBandRect) {PR_INSERT_AFTER(aBandRect, this);}
michael@0 247 void Remove() {PR_REMOVE_LINK(this);}
michael@0 248
michael@0 249 // Split the band rect into two vertically, with this band rect becoming
michael@0 250 // the top part, and a new band rect being allocated and returned for the
michael@0 251 // bottom part
michael@0 252 //
michael@0 253 // Does not insert the new band rect into the linked list
michael@0 254 BandRect* SplitVertically(nscoord aBottom);
michael@0 255
michael@0 256 // Split the band rect into two horizontally, with this band rect becoming
michael@0 257 // the left part, and a new band rect being allocated and returned for the
michael@0 258 // right part
michael@0 259 //
michael@0 260 // Does not insert the new band rect into the linked list
michael@0 261 BandRect* SplitHorizontally(nscoord aRight);
michael@0 262
michael@0 263 // Accessor functions
michael@0 264 PRBool IsOccupiedBy(const nsIFrame*) const;
michael@0 265 void AddFrame(const nsIFrame*);
michael@0 266 void RemoveFrame(const nsIFrame*);
michael@0 267 PRBool HasSameFrameList(const BandRect* aBandRect) const;
michael@0 268 int32_t Length() const;
michael@0 269 };
michael@0 270
michael@0 271 // Circular linked list of band rects
michael@0 272 struct BandList : BandRect {
michael@0 273 BandList();
michael@0 274
michael@0 275 // Accessors
michael@0 276 PRBool IsEmpty() const {return PR_CLIST_IS_EMPTY((PRCListStr*)this);}
michael@0 277 BandRect* Head() const {return (BandRect*)PR_LIST_HEAD(this);}
michael@0 278 BandRect* Tail() const {return (BandRect*)PR_LIST_TAIL(this);}
michael@0 279
michael@0 280 // Operations
michael@0 281 void Append(BandRect* aBandRect) {PR_APPEND_LINK(aBandRect, this);}
michael@0 282
michael@0 283 // Remove and delete all the band rects in the list
michael@0 284 void Clear();
michael@0 285 };
michael@0 286
michael@0 287
michael@0 288 FrameInfo* GetFrameInfoFor(nsIFrame* aFrame);
michael@0 289 FrameInfo* CreateFrameInfo(nsIFrame* aFrame, const nsRect&amp; aRect);
michael@0 290 void DestroyFrameInfo(FrameInfo*);
michael@0 291
michael@0 292 void ClearFrameInfo();
michael@0 293 void ClearBandRects();
michael@0 294
michael@0 295 BandRect* GetNextBand(const BandRect* aBandRect) const;
michael@0 296 void DivideBand(BandRect* aBand, nscoord aBottom);
michael@0 297 PRBool CanJoinBands(BandRect* aBand, BandRect* aPrevBand);
michael@0 298 PRBool JoinBands(BandRect* aBand, BandRect* aPrevBand);
michael@0 299 void AddRectToBand(BandRect* aBand, BandRect* aBandRect);
michael@0 300 void InsertBandRect(BandRect* aBandRect);
michael@0 301
michael@0 302 nsresult GetBandAvailableSpace(const BandRect* aBand,
michael@0 303 nscoord aY,
michael@0 304 const nsSize&amp; aMaxSize,
michael@0 305 nsBandData&amp; aAvailableSpace) const;
michael@0 306
michael@0 307 nsIFrame* const mFrame; // frame associated with the space manager
michael@0 308 nscoord mX, mY; // translation from local to global coordinate space
michael@0 309 BandList mBandList; // header/sentinel for circular linked list of band rects
michael@0 310 FrameInfo* mFrameInfoMap;
michael@0 311 nsIntervalSet mFloatDamage;
michael@0 312
michael@0 313 static int32_t sCachedSpaceManagerCount;
michael@0 314 static void* sCachedSpaceManagers[NS_SPACE_MANAGER_CACHE_SIZE];
michael@0 315
michael@0 316 nsSpaceManager(const nsSpaceManager&amp;); // no implementation
michael@0 317 void operator=(const nsSpaceManager&amp;); // no implementation
michael@0 318 };
michael@0 319
michael@0 320 </pre>
michael@0 321
michael@0 322 <h3>Public API</h3>
michael@0 323
michael@0 324 <h4>Life Cycle:</h4>
michael@0 325 <p>
michael@0 326 The Constructor requires a Presentation Shell, used for arena allocations
michael@0 327 mostly, and a frame that this Space Manager is rooted on. &nbsp;The coordinate
michael@0 328 space of this Space Manager is relative to the frame passed in to the constructor.
michael@0 329 </p>
michael@0 330
michael@0 331 <pre> nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
michael@0 332 ~nsSpaceManager();
michael@0 333 </pre>
michael@0 334 <p>
michael@0 335 Operators 'new' and 'delete' are overridden to support a recycler. &nbsp;Space
michael@0 336 Manager instances come and go pretty frequently, and this recycler prevents
michael@0 337 excessive heap allocations and the performance penalties associated with
michael@0 338 it. The #define NS_SPACE_MANAGER_CACHE_SIZE is used to control the number
michael@0 339 of Space Manager instances that can be present in the recycler, currently
michael@0 340 4. &nbsp;If more than NS_SPACE_MANAGER_CACHE_SIZE are allocated at a time,
michael@0 341 then standard allocation is used.
michael@0 342 </p>
michael@0 343
michael@0 344 <pre>
michael@0 345 void* operator new(size_t aSize);
michael@0 346 void operator delete(void* aPtr, size_t aSize);
michael@0 347
michael@0 348 </pre>
michael@0 349 <p>
michael@0 350 A Static method is used to shutdown the Space Manager recycling. &nbsp;This
michael@0 351 method deletes all of the Space Mangers inthe recycler,and prevents further
michael@0 352 recycling. &nbsp;It is meant to be called only when the layout module is being
michael@0 353 terminated.
michael@0 354 </p>
michael@0 355
michael@0 356 <pre> static void Shutdown();
michael@0 357
michael@0 358 </pre>
michael@0 359
michael@0 360 <h4>Origin / Coordinate Space Translation</h4>
michael@0 361
michael@0 362 <pre> /**
michael@0 363 * Translate the current origin by the specified (dx, dy). This
michael@0 364 * creates a new local coordinate space relative to the current
michael@0 365 * coordinate space.
michael@0 366 */
michael@0 367 void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
michael@0 368
michael@0 369 /**
michael@0 370 * Returns the current translation from local coordinate space to
michael@0 371 * world coordinate space. This represents the accumulated calls to
michael@0 372 * Translate().
michael@0 373 */
michael@0 374 void GetTranslation(nscoord&amp; aX, nscoord&amp; aY) const { aX = mX; aY = mY; }
michael@0 375
michael@0 376 /**
michael@0 377 * Returns the y-most of the bottommost band or 0 if there are no bands.
michael@0 378 *
michael@0 379 * @return PR_TRUE if there are bands and PR_FALSE if there are no bands
michael@0 380 */
michael@0 381 PRBool YMost(nscoord&amp; aYMost) const;
michael@0 382 </pre>
michael@0 383
michael@0 384 <h4>Region Management</h4>
michael@0 385
michael@0 386 <pre> /**
michael@0 387 * Returns a band starting at the specified y-offset. The band data
michael@0 388 * indicates which parts of the band are available, and which parts
michael@0 389 * are unavailable
michael@0 390 *
michael@0 391 * The band data that is returned is in the coordinate space of the
michael@0 392 * local coordinate system.
michael@0 393 *
michael@0 394 * The local coordinate space origin, the y-offset, and the max size
michael@0 395 * describe a rectangle that's used to clip the underlying band of
michael@0 396 * available space, i.e.
michael@0 397 * {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
michael@0 398 * coordinate space
michael@0 399 *
michael@0 400 * @param aYOffset the y-offset of where the band begins. The coordinate is
michael@0 401 * relative to the upper-left corner of the local coordinate space
michael@0 402 * @param aMaxSize the size to use to constrain the band data
michael@0 403 * @param aBandData [in,out] used to return the list of trapezoids that
michael@0 404 * describe the available space and the unavailable space
michael@0 405 * @return NS_OK if successful and NS_ERROR_FAILURE if the band data is not
michael@0 406 * not large enough. The 'count' member of the band data struct
michael@0 407 * indicates how large the array of trapezoids needs to be
michael@0 408 */
michael@0 409 nsresult GetBandData(nscoord aYOffset,
michael@0 410 const nsSize&amp; aMaxSize,
michael@0 411 nsBandData&amp; aBandData) const;
michael@0 412
michael@0 413 /**
michael@0 414 * Add a rectangular region of unavailable space. The space is
michael@0 415 * relative to the local coordinate system.
michael@0 416 *
michael@0 417 * The region is tagged with a frame
michael@0 418 *
michael@0 419 * @param aFrame the frame used to identify the region. Must not be NULL
michael@0 420 * @param aUnavailableSpace the bounding rect of the unavailable space
michael@0 421 * @return NS_OK if successful
michael@0 422 * NS_ERROR_FAILURE if there is already a region tagged with aFrame
michael@0 423 */
michael@0 424 nsresult AddRectRegion(nsIFrame* aFrame,
michael@0 425 const nsRect&amp; aUnavailableSpace);
michael@0 426
michael@0 427 /**
michael@0 428 * Resize the rectangular region associated with aFrame by the specified
michael@0 429 * deltas. The height change always applies to the bottom edge or the existing
michael@0 430 * rect. You specify whether the width change applies to the left or right edge
michael@0 431 *
michael@0 432 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
michael@0 433 * tagged with aFrame
michael@0 434 */
michael@0 435 enum AffectedEdge {LeftEdge, RightEdge};
michael@0 436 nsresult ResizeRectRegion(nsIFrame* aFrame,
michael@0 437 nscoord aDeltaWidth,
michael@0 438 nscoord aDeltaHeight,
michael@0 439 AffectedEdge aEdge = RightEdge);
michael@0 440
michael@0 441 /**
michael@0 442 * Offset the region associated with aFrame by the specified amount.
michael@0 443 *
michael@0 444 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
michael@0 445 * tagged with aFrame
michael@0 446 */
michael@0 447 nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);
michael@0 448
michael@0 449 /**
michael@0 450 * Remove the region associated with aFrane.
michael@0 451 *
michael@0 452 * Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
michael@0 453 * tagged with aFrame
michael@0 454 */
michael@0 455 nsresult RemoveRegion(nsIFrame* aFrame);
michael@0 456
michael@0 457 /**
michael@0 458 * Clears the list of regions representing the unavailable space.
michael@0 459 */
michael@0 460 void ClearRegions();
michael@0 461 </pre>
michael@0 462
michael@0 463 <h4>Float Impact</h4>
michael@0 464
michael@0 465 <pre> /**
michael@0 466 * Methods for dealing with the propagation of float damage during
michael@0 467 * reflow.
michael@0 468 */
michael@0 469 PRBool HasFloatDamage()
michael@0 470 {
michael@0 471 return !mFloatDamage.IsEmpty();
michael@0 472 }
michael@0 473
michael@0 474 void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
michael@0 475 {
michael@0 476 mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
michael@0 477 }
michael@0 478
michael@0 479 PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
michael@0 480 {
michael@0 481 return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
michael@0 482 }
michael@0 483 </pre>
michael@0 484
michael@0 485 <h4>Debug Only Methods</h4>
michael@0 486
michael@0 487 <pre> /**
michael@0 488 * Dump the state of the spacemanager out to a file
michael@0 489 */
michael@0 490 nsresult List(FILE* out);
michael@0 491
michael@0 492 void SizeOf(nsISizeOfHandler* aHandler, uint32_t* aResult) const;
michael@0 493
michael@0 494 </pre>
michael@0 495
michael@0 496 <h4>Unused / Obsolete Methods</h4>
michael@0 497
michael@0 498 <pre> /*
michael@0 499 * Get the frame that's associated with the space manager. This frame
michael@0 500 * created the space manager, and the world coordinate space is
michael@0 501 * relative to this frame.
michael@0 502 *
michael@0 503 * You can use QueryInterface() on this frame to get any additional
michael@0 504 * interfaces.
michael@0 505 */
michael@0 506 nsIFrame* GetFrame() const { return mFrame; }
michael@0 507
michael@0 508 </pre>
michael@0 509
michael@0 510 <h3>Implementation Notes</h3>
michael@0 511
michael@0 512 <h4></h4>
michael@0 513
michael@0 514 <h4>Algorithm 1: GetBandData</h4>
michael@0 515 <p>
michael@0 516 GetBandData is used to provide information to clients about what space if
michael@0 517 available and unavailable in a band of space. &nbsp;The client provides a
michael@0 518 vertical offset, the yOffset, that corresponds to the band that is of interest.
michael@0 519 &nbsp;This will be the y offset of the frame that is being reflowed. &nbsp;The
michael@0 520 caller also provides a collection of BandData objects (an array) and the
michael@0 521 number of items that the collection can handle. &nbsp;If the collection is
michael@0 522 too small, then an error is returned and the count is updated to indicate
michael@0 523 the size required.
michael@0 524 </p>
michael@0 525
michael@0 526 <p>
michael@0 527 The algorithm to provide the band data is as follows:
michael@0 528 </p>
michael@0 529 <ul>
michael@0 530 <li>Get a &nbsp;vertical offset in world coordinates (instead of frame-relative
michael@0 531 coordinates) by adding the y-origin of the SpaceManager to the y offset passed
michael@0 532 in</li>
michael@0 533 <li>If the (adjusted) y value passed in is greater than the greatest band
michael@0 534 being managed, then all space is available so a single trapezoid is returned,
michael@0 535 marked as available and sized to the maximum size value (passed in).</li>
michael@0 536 <li>If the (adjusted) y offset intersects a band, then gather the band
michael@0 537 data:</li>
michael@0 538 <ul>
michael@0 539 <li>walk the internal bandData list from head to tail</li>
michael@0 540 <li>for each band data entry, see if the top of the band is greater than
michael@0 541 the (adjusted) y offset requested</li>
michael@0 542 <li>if it is, then band is below the offset requested, so the area between
michael@0 543 the band and the y offset is available - create a trapezoid with that region
michael@0 544 and return it.</li>
michael@0 545 <li>if the (adjusted) y offset is between the band top and bottom, then
michael@0 546 get the available space for the band by calling GetBandAvailableSpace</li>
michael@0 547 <li>otherwise, move to the next band</li>
michael@0 548 </ul>
michael@0 549 </ul>
michael@0 550 <h5>GetBandAvailableSpace:</h5>
michael@0 551 This method is called from GetBandData only. It walks all of the bands in
michael@0 552 the space manager and determines which bands intersect with the band passed
michael@0 553 in, and if within those bands there are regions that are available or occupied.
michael@0 554
michael@0 555 <ul>
michael@0 556 <li>First, walk all of the bands until a band that is to the right of the
michael@0 557 desired offset is located</li>
michael@0 558 <li>Starting at that band, &nbsp;walk the remaining bands:</li>
michael@0 559 <ul>
michael@0 560 <li>if the current band is to the right of the requested band, then there
michael@0 561 is available space.&nbsp;</li>
michael@0 562 <ul>
michael@0 563 <li>if there is more room in the bandData collection, then add a trapezoid
michael@0 564 to the bandData collection such that it is marked as available and has a
michael@0 565 rect that represents the space between the reference band tna dht band being
michael@0 566 examined</li>
michael@0 567 <li>if there is no more room in the BandData collection, estimate the
michael@0 568 number of entries requires as the current count + twice the number of bands
michael@0 569 below the reference band, plus two. &nbsp;Return an error code so the caller
michael@0 570 can reallocate the collection and try again.</li>
michael@0 571 </ul>
michael@0 572 <li>check the size of the collection again, if there is no room left
michael@0 573 then estimate the number of items requires as the current count + twice the
michael@0 574 number of bands below the band in question plus one.&nbsp;</li>
michael@0 575 <li>create a new trapezoid in the band collection that has a region corresponding
michael@0 576 to the reference band rect, marked as occupied by either a single or multiple
michael@0 577 frames.</li>
michael@0 578 <li>move to the next band</li>
michael@0 579 </ul>
michael@0 580 <li>after walking all of the band data, se if we have reached the right
michael@0 581 edge of the band.&nbsp;</li>
michael@0 582 <ul>
michael@0 583 <li>If not, then check for space in the band collection</li>
michael@0 584 <ul>
michael@0 585 <li>if there is no room left, then set the count to the current count
michael@0 586 plus 1 and return an error.</li>
michael@0 587 <li>otherwise, create another entry in the band collection, marked
michael@0 588 as available, and with a rect corresponding to the area remainin in the band
michael@0 589 (eg. from the right edge of the last band rect to the right edge of the band).</li>
michael@0 590 </ul>
michael@0 591 </ul>
michael@0 592 </ul>
michael@0 593
michael@0 594 <h4>Algorithm 2: AddRectRegion</h4>
michael@0 595 Clients call into this method to notify the Space Manager that a new frame
michael@0 596 is occupying some space.
michael@0 597
michael@0 598 <ul>
michael@0 599 <li>First, try to get frame info for the frame. If it is found, return
michael@0 600 an error since the frame is already associated with a region in the Space
michael@0 601 Manager.</li>
michael@0 602 <li>Next, create a rect from the occupied space passed in by the caller,
michael@0 603 transforming it first to world-coordinates by adding the Space Manager's
michael@0 604 offset to the occupied space rect passed in.</li>
michael@0 605 <li>Create a new Frame Info instance for the frame and rect, returning
michael@0 606 an error if allocation fails.</li>
michael@0 607 <li>Check if the occupied space rect (adjusted) is empty, if so, return
michael@0 608 an error &nbsp;(<font color="#cc0000">NOTE: this could be done earlier, or
michael@0 609 prevented by the caller</font>)</li>
michael@0 610 <li>Allocate a new BandRect instance with the rect and frame as constructor
michael@0 611 arguments, and insert it into the collection via InsertBandRect</li>
michael@0 612 </ul>
michael@0 613 <h5>InsertBandRect:</h5>
michael@0 614 Internal method to insert a band rect into the BandList in the correct location.
michael@0 615 There are several cases it has to handle, as specified in the source file
michael@0 616 comments:
michael@0 617
michael@0 618 <pre>// When comparing a rect to a band there are seven cases to consider.
michael@0 619 // 'R' is the rect and 'B' is the band.
michael@0 620 //
michael@0 621 // Case 1 Case 2 Case 3 Case 4
michael@0 622 // ------ ------ ------ ------
michael@0 623 // +-----+ +-----+ +-----+ +-----+
michael@0 624 // | R | | R | +-----+ +-----+ | | | |
michael@0 625 // +-----+ +-----+ | | | R | | B | | B |
michael@0 626 // +-----+ | B | +-----+ | | +-----+ | |
michael@0 627 // | | | | +-----+ | R | +-----+
michael@0 628 // | B | +-----+ +-----+
michael@0 629 // | |
michael@0 630 // +-----+
michael@0 631 //
michael@0 632 //
michael@0 633 //
michael@0 634 // Case 5 Case 6 Case 7
michael@0 635 // ------ ------ ------
michael@0 636 // +-----+ +-----+ +-----+ +-----+
michael@0 637 // | | | R | | B | | | +-----+
michael@0 638 // | B | +-----+ +-----+ | R | | B |
michael@0 639 // | | | | +-----+
michael@0 640 // +-----+ +-----+
michael@0 641 // +-----+
michael@0 642 // | R |
michael@0 643 // +-----+
michael@0 644 //
michael@0 645 </pre>
michael@0 646 <ul>
michael@0 647 <li>First, check for the easiest case, where there are no existing band
michael@0 648 rects, or the band rect passed in is below the bottommost rect. In this case,
michael@0 649 just append the band rect and return.</li>
michael@0 650 <li>Starting at the head of the list of bandRects, check for intersection
michael@0 651 with the rect passed in:</li>
michael@0 652 <ul>
michael@0 653 <li>case #1: the rect is totally above the current band rect, so insert
michael@0 654 a new band rect before the current bandRect</li>
michael@0 655 <li>cases #2 and #7: the rect is partially above the band rect, so it
michael@0 656 is divided into two bandRects, one entirely above the band, and one containing
michael@0 657 the remainder of the rect. &nbsp;Insert the part that is totally above the
michael@0 658 bandRect before the current bandRect, as in case #1 above, and adjust the
michael@0 659 other band rect to exclude the part already added.</li>
michael@0 660 <li>case #5: the rect is totally below the current bandRect, so just
michael@0 661 skip to the next band</li>
michael@0 662 <li>case #3 and #4: rect is at least partially intersection with the
michael@0 663 bandRect, so divide the current band into two parts, where the top part is
michael@0 664 above the current rect. &nbsp;Move to the new band just created, which is
michael@0 665 the next band.</li>
michael@0 666 <li>case #6: the rect shares the bottom and height with the bandRect,
michael@0 667 so just add the rect to the band.</li>
michael@0 668 <li>case #4 and #7: create a new rect for the part that overlaps the
michael@0 669 bandRect, and add it to the current bandRect (similar to case #6) and then
michael@0 670 move on to the next band, removing that part from the rect passed in. &nbsp;If
michael@0 671 no more bands, append the rect passed in to the end of the bandRect list.</li>
michael@0 672 </ul>
michael@0 673 </ul>
michael@0 674 <i>This algorithm is pretty confusing - basically what needs to happen is
michael@0 675 that rects and bands need to be divided up so that complicated cases like
michael@0 676 #2, #4, and #7, are reduced to simpler cases where the rects is totally above,
michael@0 677 below, or between a band rect. &nbsp;From the current implementation, it
michael@0 678 might be worth verifying that the final result of the inserts is a correctly
michael@0 679 ordered liest of bandRects (debug mode only).</i>
michael@0 680
michael@0 681
michael@0 682 <h4>Algorithm 3: RemoveRegion</h4>
michael@0 683 When a float is removed, the Space Manager is notified by a call to RemoveRegion,
michael@0 684 passing in the frame that is being removed.
michael@0 685
michael@0 686 <ul>
michael@0 687 <li>Get the FrameInfo for the frame passed in. If not found, an error is
michael@0 688 returned.</li>
michael@0 689 <li>If the rect for the frame is not empty, then visit each band in the
michael@0 690 bandList:</li>
michael@0 691 <ul>
michael@0 692 <li>for each rect in the band:
michael@0 693
michael@0 694 </li>
michael@0 695 </ul>
michael@0 696 <ul>
michael@0 697 <ul>
michael@0 698 <li>if the bandRect is occupied by the frame, either remove the frame
michael@0 699 from the bandRect (if there are other frames sharing it) and remember that
michael@0 700 it was shared</li>
michael@0 701 <li>otherwise simply remove the bandRect (no other frames share it).</li>
michael@0 702 <li>if the bandRect was shared, then try to coalesce adjacent bandRects</li>
michael@0 703 <ul>
michael@0 704 <li>if the previous bandRect is directly next to the current bandRect,
michael@0 705 and they have the same frame list, then make the current bandRect cover the
michael@0 706 previous bandRect's full region (adjust the left edge to be that of the previous
michael@0 707 bandRect) and remove the previous bandRect.</li>
michael@0 708 </ul>
michael@0 709 </ul>
michael@0 710 </ul>
michael@0 711 <ul>
michael@0 712 <li>if the current band or prior band had a rect occupied byu the frame,
michael@0 713 then try to join the two bands via JoinBands</li>
michael@0 714 </ul>
michael@0 715 <li>Finally, destroy the frameInfo for the frame.
michael@0 716
michael@0 717 </li>
michael@0 718 </ul>
michael@0 719
michael@0 720 <br>
michael@0 721
michael@0 722 <hr width="100%" size="2">
michael@0 723 <h2>Cross-Component Algorithms</h2>
michael@0 724
michael@0 725 <br>
michael@0 726
michael@0 727
michael@0 728
michael@0 729 <hr width="100%" size="2">
michael@0 730 <h2>Tech Notes</h2>
michael@0 731 <ul>
michael@0 732 <li>
michael@0 733
michael@0 734 </li>
michael@0 735
michael@0 736 </ul>
michael@0 737
michael@0 738
michael@0 739
michael@0 740
michael@0 741
michael@0 742 </body>
michael@0 743 </html>

mercurial