Back to index

lightning-sunbird  0.9+nobinonly
celldata.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #ifndef CellData_h__
00038 #define CellData_h__
00039 
00040 #include "nsISupports.h"
00041 #include "nsCoord.h"
00042 
00043 #define MAX_ROWSPAN 8190 // the cellmap can not handle more
00044 #define MAX_COLSPAN 1000 // limit as IE and opera do
00045 
00046 class nsTableCellFrame;
00047 
00051 class CellData
00052 {
00053 public:
00057   CellData(nsTableCellFrame* aOrigCell);
00058 
00060   ~CellData(); //the constructor and destructor are implemented in nsCellMap.cpp
00061 
00065   void   Init(nsTableCellFrame* aCellFrame);
00066 
00070   PRBool IsOrig() const;
00071 
00077   PRBool IsDead() const;
00078 
00082   PRBool IsSpan() const;
00083 
00087   PRBool IsRowSpan() const;
00088   
00094   PRBool IsZeroRowSpan() const;
00095 
00099   void SetZeroRowSpan(PRBool aIsZero);
00100 
00104   PRUint32 GetRowSpanOffset() const;
00105 
00109   void SetRowSpanOffset(PRUint32 aSpan);
00110 
00114   PRBool IsColSpan() const;
00115 
00122   PRBool IsZeroColSpan() const;
00123 
00127   void SetZeroColSpan(PRBool aIsZero);
00128 
00132   PRUint32 GetColSpanOffset() const;
00133 
00137   void SetColSpanOffset(PRUint32 aSpan);
00138   
00142   PRBool IsOverlap() const;
00143 
00147   void SetOverlap(PRBool aOverlap);
00148   
00153   nsTableCellFrame* GetCellFrame() const;
00154 
00155 protected:
00156 
00157   // this union relies on the assumption that an object (not primitive type) does
00158   // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect 
00159   // and the data does not represent a span. If mSpan is 1, then mBits is in
00160   // effect and the data represents a span.
00161   // mBits must be an unsigned long because it must match the size of 
00162   // mOrigCell on both 32- and 64-bit platforms.
00163   union {
00164     nsTableCellFrame* mOrigCell;
00165     unsigned long     mBits;
00166   };
00167 };
00168 
00169 // Border Collapsing Cell Data
00170 enum BCBorderOwner 
00171 {
00172   eTableOwner        =  0,
00173   eColGroupOwner     =  1, 
00174   eAjaColGroupOwner  =  2, // col group to the left 
00175   eColOwner          =  3,
00176   eAjaColOwner       =  4, // col to the left
00177   eRowGroupOwner     =  5, 
00178   eAjaRowGroupOwner  =  6, // row group above
00179   eRowOwner          =  7, 
00180   eAjaRowOwner       =  8, // row above
00181   eCellOwner         =  9,
00182   eAjaCellOwner      = 10  // cell to the top or to the left
00183 };
00184 
00185 typedef PRUint16 BCPixelSize;
00186 
00187 // These are the max sizes that are stored. If they are exceeded, then the max is stored and
00188 // the actual value is computed when needed.
00189 #define MAX_BORDER_WIDTH nscoord(PR_BITMASK(sizeof(BCPixelSize) * 8))
00190 
00191 #define BC_BORDER_TOP_HALF_COORD(p2t,px)    NSToCoordRound(float((px) - (px) / 2) * (p2t) )
00192 #define BC_BORDER_RIGHT_HALF_COORD(p2t,px)  NSToCoordRound(float(       (px) / 2) * (p2t) )
00193 #define BC_BORDER_BOTTOM_HALF_COORD(p2t,px) NSToCoordRound(float(       (px) / 2) * (p2t) )
00194 #define BC_BORDER_LEFT_HALF_COORD(p2t,px)   NSToCoordRound(float((px) - (px) / 2) * (p2t) )
00195 
00196 #define BC_BORDER_TOP_HALF(px)    ((px) - (px) / 2)
00197 #define BC_BORDER_RIGHT_HALF(px)  ((px) / 2)
00198 #define BC_BORDER_BOTTOM_HALF(px) ((px) / 2)
00199 #define BC_BORDER_LEFT_HALF(px)   ((px) - (px) / 2)
00200 
00201 // BCData stores the top and left border info and the corner connecting the two.
00202 class BCData
00203 {
00204 public:
00205   BCData();
00206 
00207   ~BCData();
00208 
00209   nscoord GetLeftEdge(BCBorderOwner& aOwner,
00210                       PRBool&        aStart) const;
00211 
00212   void SetLeftEdge(BCBorderOwner aOwner,
00213                    nscoord       aSize,
00214                    PRBool        aStart);
00215 
00216   nscoord GetTopEdge(BCBorderOwner& aOwner,
00217                      PRBool&        aStart) const;
00218 
00219   void SetTopEdge(BCBorderOwner aOwner,
00220                   nscoord       aSize,
00221                   PRBool        aStart);
00222 
00223   BCPixelSize GetCorner(PRUint8&       aCornerOwner,
00224                         PRPackedBool&  aBevel) const;
00225 
00226   void SetCorner(BCPixelSize aSubSize,
00227                  PRUint8 aOwner,
00228                  PRBool  aBevel);
00229 
00230   PRBool IsLeftStart() const;
00231 
00232   void SetLeftStart(PRBool aValue);
00233 
00234   PRBool IsTopStart() const;
00235 
00236   void SetTopStart(PRBool aValue);
00237 
00238                
00239 protected:
00240   BCPixelSize mLeftSize;      // size in pixels of left border
00241   BCPixelSize mTopSize;       // size in pixels of top border
00242   BCPixelSize mCornerSubSize; // size of the largest border not in the
00243                               //   dominant plane (for example, if corner is
00244                               //   owned by the segment to its top or bottom,
00245                               //   then the size is the max of the border
00246                               //   sizes of the segments to its left or right.
00247   unsigned mLeftOwner:     4; // owner of left border     
00248   unsigned mTopOwner:      4; // owner of top border    
00249   unsigned mLeftStart:     1; // set if this is the start of a vertical border segment
00250   unsigned mTopStart:      1; // set if this is the start of a horizontal border segment
00251   unsigned mCornerSide:    2; // side of the owner of the upper left corner relative to the corner
00252   unsigned mCornerBevel:   1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
00253 };
00254 
00255 // BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
00256 // effect. BCData for a row and col entry contains the left and top borders of cell at that row and 
00257 // col and the corner connecting the two. The right borders of the cells in the last col and the bottom
00258 // borders of the last row are stored in separate BCData entries in the cell map.
00259 class BCCellData : public CellData
00260 {
00261 public:
00262   BCCellData(nsTableCellFrame* aOrigCell);
00263   ~BCCellData();
00264 
00265   BCData mData;
00266 };
00267 
00268 
00269 #define SPAN             0x00000001 // there a row or col span 
00270 #define ROW_SPAN         0x00000002 // there is a row span
00271 #define ROW_SPAN_0       0x00000004 // the row span is 0
00272 #define ROW_SPAN_OFFSET  0x0000FFF8 // the row offset to the data containing the original cell
00273 #define COL_SPAN         0x00010000 // there is a col span
00274 #define COL_SPAN_0       0x00020000 // the col span is 0
00275 #define OVERLAP          0x00040000 // there is a row span and col span but no by same cell
00276 #define COL_SPAN_OFFSET  0xFFF80000 // the col offset to the data containing the original cell
00277 #define ROW_SPAN_SHIFT   3          // num bits to shift to get right justified row span
00278 #define COL_SPAN_SHIFT   19         // num bits to shift to get right justified col span
00279 
00280 inline nsTableCellFrame* CellData::GetCellFrame() const
00281 {
00282   if (SPAN != (SPAN & mBits)) {
00283     return mOrigCell;
00284   }
00285   return nsnull;
00286 }
00287 
00288 inline void CellData::Init(nsTableCellFrame* aCellFrame) 
00289 {
00290   mOrigCell = aCellFrame;
00291 }
00292 
00293 inline PRBool CellData::IsOrig() const
00294 {
00295   return ((nsnull != mOrigCell) && (SPAN != (SPAN & mBits)));
00296 }
00297 
00298 inline PRBool CellData::IsDead() const
00299 {
00300   return (0 == mBits);
00301 }
00302 
00303 inline PRBool CellData::IsSpan() const
00304 {
00305   return (SPAN == (SPAN & mBits));
00306 }
00307 
00308 inline PRBool CellData::IsRowSpan() const
00309 {
00310   return (SPAN     == (SPAN & mBits)) && 
00311          (ROW_SPAN == (ROW_SPAN & mBits));
00312 }
00313 
00314 inline PRBool CellData::IsZeroRowSpan() const
00315 {
00316   return (SPAN       == (SPAN & mBits))     && 
00317          (ROW_SPAN   == (ROW_SPAN & mBits)) &&
00318          (ROW_SPAN_0 == (ROW_SPAN_0 & mBits));
00319 }
00320 
00321 inline void CellData::SetZeroRowSpan(PRBool aIsZeroSpan)
00322 {
00323   if (SPAN == (SPAN & mBits)) {
00324     if (aIsZeroSpan) {
00325       mBits |= ROW_SPAN_0;
00326     }
00327     else {
00328       mBits &= ~ROW_SPAN_0;
00329     }
00330   }
00331 }
00332 
00333 inline PRUint32 CellData::GetRowSpanOffset() const
00334 {
00335   if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) {
00336     return (PRUint32)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT);
00337   }
00338   return 0;
00339 }
00340 
00341 inline void CellData::SetRowSpanOffset(PRUint32 aSpan) 
00342 {
00343   mBits &= ~ROW_SPAN_OFFSET;
00344   mBits |= (aSpan << ROW_SPAN_SHIFT);
00345   mBits |= SPAN;
00346   mBits |= ROW_SPAN;
00347 }
00348 
00349 inline PRBool CellData::IsColSpan() const
00350 {
00351   return (SPAN     == (SPAN & mBits)) && 
00352          (COL_SPAN == (COL_SPAN & mBits));
00353 }
00354 
00355 inline PRBool CellData::IsZeroColSpan() const
00356 {
00357   return (SPAN       == (SPAN & mBits))     && 
00358          (COL_SPAN   == (COL_SPAN & mBits)) &&
00359          (COL_SPAN_0 == (COL_SPAN_0 & mBits));
00360 }
00361 
00362 inline void CellData::SetZeroColSpan(PRBool aIsZeroSpan)
00363 {
00364   if (SPAN == (SPAN & mBits)) {
00365     if (aIsZeroSpan) {
00366       mBits |= COL_SPAN_0;
00367     }
00368     else {
00369       mBits &= ~COL_SPAN_0;
00370     }
00371   }
00372 }
00373 
00374 inline PRUint32 CellData::GetColSpanOffset() const
00375 {
00376   if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) {
00377     return (PRUint32)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT);
00378   }
00379   return 0;
00380 }
00381 
00382 inline void CellData::SetColSpanOffset(PRUint32 aSpan) 
00383 {
00384   mBits &= ~COL_SPAN_OFFSET;
00385   mBits |= (aSpan << COL_SPAN_SHIFT);
00386 
00387   mBits |= SPAN;
00388   mBits |= COL_SPAN;
00389 }
00390 
00391 inline PRBool CellData::IsOverlap() const
00392 {
00393   return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits));
00394 }
00395 
00396 inline void CellData::SetOverlap(PRBool aOverlap) 
00397 {
00398   if (SPAN == (SPAN & mBits)) {
00399     if (aOverlap) {
00400       mBits |= OVERLAP;
00401     }
00402     else {
00403       mBits &= ~OVERLAP;
00404     }
00405   }
00406 }
00407 
00408 inline BCData::BCData()
00409 {
00410   mLeftOwner = mTopOwner = eCellOwner;
00411   mLeftStart = mTopStart = 1;
00412   mLeftSize = mCornerSide = mCornerSubSize = mTopSize = 0;
00413   mCornerBevel = PR_FALSE;
00414 }
00415 
00416 inline BCData::~BCData()
00417 {
00418 }
00419 
00420 inline nscoord BCData::GetLeftEdge(BCBorderOwner& aOwner,
00421                                    PRBool&        aStart) const
00422 {
00423   aOwner = (BCBorderOwner)mLeftOwner;
00424   aStart = (PRBool)mLeftStart;
00425 
00426   return (nscoord)mLeftSize;
00427 }
00428 
00429 inline void BCData::SetLeftEdge(BCBorderOwner  aOwner,
00430                                 nscoord        aSize,
00431                                 PRBool         aStart)
00432 {
00433   mLeftOwner = aOwner;
00434   mLeftSize  = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
00435   mLeftStart = aStart;
00436 }
00437 
00438 inline nscoord BCData::GetTopEdge(BCBorderOwner& aOwner,
00439                                   PRBool&        aStart) const
00440 {
00441   aOwner = (BCBorderOwner)mTopOwner;
00442   aStart = (PRBool)mTopStart;
00443 
00444   return (nscoord)mTopSize;
00445 }
00446 
00447 inline void BCData::SetTopEdge(BCBorderOwner  aOwner,
00448                                nscoord        aSize,
00449                                PRBool         aStart)
00450 {
00451   mTopOwner = aOwner;
00452   mTopSize  = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
00453   mTopStart = aStart;
00454 }
00455 
00456 inline BCPixelSize BCData::GetCorner(PRUint8&       aOwnerSide,
00457                                      PRPackedBool&  aBevel) const
00458 {
00459   aOwnerSide = mCornerSide;
00460   aBevel     = (PRBool)mCornerBevel;
00461   return mCornerSubSize;
00462 }
00463 
00464 inline void BCData::SetCorner(BCPixelSize aSubSize,
00465                               PRUint8 aOwnerSide,
00466                               PRBool  aBevel)
00467 {
00468   mCornerSubSize = aSubSize;
00469   mCornerSide    = aOwnerSide;
00470   mCornerBevel   = aBevel;
00471 }
00472 
00473 inline PRBool BCData::IsLeftStart() const
00474 {
00475   return (PRBool)mLeftStart;
00476 }
00477 
00478 inline void BCData::SetLeftStart(PRBool aValue)
00479 {
00480   mLeftStart = aValue;
00481 }
00482 
00483 inline PRBool BCData::IsTopStart() const
00484 {
00485   return (PRBool)mTopStart;
00486 }
00487 
00488 inline void BCData::SetTopStart(PRBool aValue)
00489 {
00490   mTopStart = aValue;
00491 }
00492 
00493 #endif