include/HTMLRenderer/GenericRenderer.hpp

Go to the documentation of this file.
00001 #ifndef hpp_CPP_GenericRenderer_CPP_hpp
00002 #define hpp_CPP_GenericRenderer_CPP_hpp
00003 
00004 // We need CSS units for the box model
00005 #include "../CSS/CSSUnit.hpp"
00006 // We need the mapper declaration (to be checked)
00007 #include "Mapper.hpp"
00008 
00009 namespace HTML
00010 {
00012     namespace Renderer
00013     {
00027         class Box
00028         {
00029             // The used unit
00030         public:
00032             typedef CSS::Length                 Length;
00034             typedef CSS::Colour                 Colour;
00036             typedef CSS::LineHeight             LineHeight;
00038             typedef CSS::Font                   Font;
00040             typedef CSS::DisplayMode::Type      DisplayMode;
00042             typedef CSS::TextAlign              TextAlign;
00044             typedef CSS::VerticalAlign          VerticalAlign;
00046             typedef CSS::TextDecoration::Type   TextDecoration;
00047 
00048             
00049             // Declared members
00050         private:
00055             struct Content
00056             {
00058                 Length *    width;
00060                 Length *    height;
00061 
00063                 Content(Length * _width = 0, Length * _height = 0) : width(_width), height(_height) {}
00065                 ~Content() { }
00066 
00068                 inline uint32 getWidth(const uint32 iteration) const { if (width) return (uint32)width->getAsPixels(iteration); return 0; }
00070                 inline uint32 getHeight(const uint32 iteration) const { if (height) return (uint32)height->getAsPixels(iteration); return 0; }
00071 
00073                 inline void setComputedWidth(const uint32 newWidth, const uint32 iteration) const { if (width) width->setComputedValue(newWidth, iteration); }
00075                 inline void setComputedHeight(const uint32 newHeight, const uint32 iteration) const { if (height) height->setComputedValue(newHeight, iteration); }
00076             };
00077 
00083             struct Rectangle
00084             {
00086                 Length *    top;
00088                 Length *    bottom;
00090                 Length *    left;
00092                 Length *    right;
00093 
00095                 Rectangle(Length * _top = 0, Length * _left = 0, Length * _right = 0, Length * _bottom = 0) : top(_top), bottom(_bottom), left(_left), right(_right) {}
00097                 ~Rectangle() { }
00098 
00100                 inline int32 getWidth(const uint32 iteration) const { return (left ? left->getAsPixels(iteration) : 0) + (right ? right->getAsPixels(iteration) : 0); }
00102                 inline int32 getLeftWidth(const uint32 iteration) const { return (left ? left->getAsPixels(iteration) : 0); }
00104                 inline int32 getRightWidth(const uint32 iteration) const { return (right ? right->getAsPixels(iteration) : 0); }
00106                 inline int32 getHeight(const uint32 iteration) const { return (top ? top->getAsPixels(iteration) : 0) + (bottom ? bottom->getAsPixels(iteration) : 0);}
00108                 inline int32 getTopWidth(const uint32 iteration) const { return (top ? top->getAsPixels(iteration) : 0); }
00110                 inline int32 getBottomWidth(const uint32 iteration) const { return (bottom ? bottom->getAsPixels(iteration) : 0); }
00111 
00113                 inline void setLeftWidth(const int32 width, const uint32 iteration) const { if (left) left->setComputedValue(width, iteration); }
00115                 inline void setRightWidth(const int32 width, const uint32 iteration) const { if (right) right->setComputedValue(width, iteration); }
00116 
00118                 inline void setTopHeight(const int32 height, const uint32 iteration) const { if (top) top->setComputedValue(height, iteration); }
00120                 inline void setBottomHeight(const int32 height, const uint32 iteration) const { if (bottom) bottom->setComputedValue(height, iteration); }
00121             };
00122 
00124             typedef Rectangle Padding;
00126             typedef Rectangle Margin;
00127 
00129             struct Border
00130             {
00135                 struct Side
00136                 {
00138                     typedef CSS::BorderStyle::Style    BorderStyle;
00139 
00140                     // Members
00141                 private:
00143                     Length *        length;
00145                     BorderStyle     style;
00147                     Colour          color;
00148 
00149                 public:    
00151                     Side(Length * len = 0, const BorderStyle _style = CSS::BorderStyle::None, const Colour & colour = CSS::Colours::Black) : length(len), style(_style), color(colour) { checkLength(); }  
00153                     ~Side() {  }
00154 
00156                     inline void setStyle(const BorderStyle _style) {  style = _style; checkLength(); }
00158                     inline void checkLength() { if (length && (style == CSS::BorderStyle::None || style == CSS::BorderStyle::Hidden)) length->setZero(); }
00160                     inline int32 getAsPixels(const uint32 iteration) const { if (length) return length->getAsPixels(iteration); return 0; }
00162                     inline BorderStyle getStyle() const { return style; }
00164                     inline bool isVisible() const { return style != CSS::BorderStyle::None && style != CSS::BorderStyle::Hidden; }
00166                     inline bool isAuto() const { return (length ? length->isAuto() : false); }
00168                     inline const Colour & getColour() const { return color; } 
00169 
00171                     inline void setValue(const int32 value, const uint32 iteration) const { if (length && style != CSS::BorderStyle::None && style != CSS::BorderStyle::Hidden) length->setComputedValue(value, iteration); }
00172 
00173                     friend class HTML::Renderer::Box;
00174                 };
00175 
00176 
00178                 Side        top;
00180                 Side        bottom;
00182                 Side        left;
00184                 Side        right;
00185 
00187                 Border(Length * _top = 0, const Side::BorderStyle topStyle = CSS::BorderStyle::None, const Colour & topColor = CSS::Colours::Black,
00188                        Length * _left = 0, const Side::BorderStyle leftStyle = CSS::BorderStyle::None, const Colour & leftColor = CSS::Colours::Black,
00189                        Length * _right = 0, const Side::BorderStyle rightStyle = CSS::BorderStyle::None, const Colour & rightColor = CSS::Colours::Black, 
00190                        Length * _bottom = 0, const Side::BorderStyle bottomStyle = CSS::BorderStyle::None, const Colour & bottomColor = CSS::Colours::Black)
00191                      : top(_top, topStyle, topColor), bottom(_bottom, bottomStyle, bottomColor), 
00192                        left(_left, leftStyle, leftColor), right(_right, rightStyle, rightColor) {}
00193 
00195                 inline int32 getWidth(const uint32 iteration) const { return left.getAsPixels(iteration) + right.getAsPixels(iteration); }
00197                 inline int32 getLeftWidth(const uint32 iteration) const { return left.getAsPixels(iteration); }
00199                 inline int32 getRightWidth(const uint32 iteration) const { return right.getAsPixels(iteration); }
00201                 inline int32 getHeight(const uint32 iteration) const { return top.getAsPixels(iteration) + bottom.getAsPixels(iteration);}
00203                 inline int32 getTopWidth(const uint32 iteration) const { return top.getAsPixels(iteration); }
00205                 inline int32 getBottomWidth(const uint32 iteration) const { return bottom.getAsPixels(iteration); }
00206 
00208                 inline void setLeftWidth(const int32 width, const uint32 iteration) const { left.setValue(width, iteration); }
00210                 inline void setRightWidth(const int32 width, const uint32 iteration) const { right.setValue(width, iteration); }
00212                 inline void setTopHeight(const int32 height, const uint32 iteration) const { top.setValue(height, iteration); }
00214                 inline void setBottomHeight(const int32 height, const uint32 iteration) const { bottom.setValue(height, iteration); }
00215             };
00216 
00218             struct BoxSizes
00219             {
00221                 Content    content;
00223                 Padding    padding;
00225                 Border     border;
00227                 Margin     margin;
00228 
00230                 BoxSizes(   Length * width = 0, Length * height = 0,
00231                             Length * paddingTop = 0, Length * paddingLeft = 0, Length * paddingRight = 0, Length * paddingBottom = 0,
00232                             Length * marginTop = 0, Length * marginLeft = 0, Length * marginRight = 0, Length * marginBottom = 0,
00233                             Length * borderTop = 0, const CSS::BorderStyle::Style topStyle = CSS::BorderStyle::None, const Colour & topColor = CSS::Colours::Black,
00234                             Length * borderLeft = 0, const CSS::BorderStyle::Style leftStyle = CSS::BorderStyle::None, const Colour & leftColor = CSS::Colours::Black,
00235                             Length * borderRight = 0, const CSS::BorderStyle::Style rightStyle = CSS::BorderStyle::None, const Colour & rightColor = CSS::Colours::Black,
00236                             Length * borderBottom = 0, const CSS::BorderStyle::Style bottomStyle = CSS::BorderStyle::None, const Colour & bottomColor = CSS::Colours::Black) 
00237                           : content(width, height),
00238                             padding(paddingTop, paddingLeft, paddingRight, paddingBottom),
00239                             margin(marginTop, marginLeft, marginRight, marginBottom),
00240                             border(borderTop, topStyle, topColor, 
00241                                    borderLeft, leftStyle, leftColor,
00242                                    borderRight, rightStyle, rightColor,
00243                                    borderBottom, bottomStyle, bottomColor) { }
00244             };
00245 
00250             struct Position
00251             {
00253                 typedef CSS::Position::Type Type;
00255                 Type        type;
00257                 Length *    top;
00259                 Length *    bottom;
00261                 Length *    left;
00263                 Length *    right;
00264                 
00266                 inline bool absolutelyPositioned() const { return type == CSS::Position::Absolute || type == CSS::Position::Fixed; }
00267 
00269                 inline int32 getLeft(const uint32 iteration) const { return left ? left->getAsPixels(iteration) : 0; }
00271                 inline int32 getRight(const uint32 iteration) const { return right ? right->getAsPixels(iteration) : 0; }
00273                 inline int32 getTop(const uint32 iteration) const { return top ? top->getAsPixels(iteration) : 0; }
00275                 inline int32 getBottom(const uint32 iteration) const { return bottom ? bottom->getAsPixels(iteration) : 0; }
00276 
00278                 inline void setLeft(const int32 width, const uint32 iteration) const { if (left) left->setComputedValue(width, iteration); }
00280                 inline void setRight(const int32 width, const uint32 iteration) const { if (right) right->setComputedValue(width, iteration); }
00282                 inline void setTop(const int32 height, const uint32 iteration) const { if (top) top->setComputedValue(height, iteration); }
00284                 inline void setBottom(const int32 height, const uint32 iteration) const { if (bottom) bottom->setComputedValue(height, iteration); }
00285 
00287                 Position(const Type & _type = CSS::Position::Static, Length * _top = 0, Length * _left = 0, Length * _right = 0, Length * _bottom = 0) : type(_type), top(_top), bottom(_bottom), left(_left), right(_right) {}
00290                 ~Position() { delete top; delete bottom; delete left; delete right; }
00291             };
00292 
00294             struct ComputedPosition
00295             {
00297                 int32    top;
00299                 int32    bottom;
00301                 int32    left;
00303                 int32    right;
00304 
00306                 inline void Reset() { top = bottom = left = right = 0; }
00309                 inline int32 getWidth() const { return left + right; }
00312                 inline int32 getHeight() const { return top + bottom;}
00316                 inline int32 getTrueWidth() const { return left + (right > 0 ? right : 0); }
00320                 inline int32 getTrueHeight() const { return top + (bottom > 0 ? bottom : 0);}
00321 
00323                 ComputedPosition() : top(0), bottom(0), left(0), right(0) {}
00324             };
00325 
00327             struct ComputedContent
00328             {
00330                 uint32 width;
00332                 uint32 height;
00333 
00335                 inline uint32 getWidth() const { return width; }
00337                 inline uint32 getHeight() const { return height; }
00338 
00340                 inline void Reset() { width = height = 0; }
00341             };
00342 
00344             struct ComputedBoxSizes
00345             {
00347                 ComputedContent     content;
00349                 ComputedPosition    padding;
00351                 ComputedPosition    border;
00353                 ComputedPosition    margin; 
00354 
00356                 inline void Reset() { content.Reset(); padding.Reset(); border.Reset(); margin.Reset(); }
00357             };
00358 
00360             struct ClearAndFloat
00361             {
00363                 typedef CSS::ClearAndFloat::Property Property;
00364 
00366                 Property floating;
00368                 Property clearing;
00369 
00371                 inline const Property getFloat() const { return floating; }
00373                 inline const Property getClear() const { return clearing; }
00374 
00376                 inline bool isClearFromLeft() const { return clearing == CSS::ClearAndFloat::Left || clearing == CSS::ClearAndFloat::Both; }
00378                 inline bool isClearFromRight() const { return clearing == CSS::ClearAndFloat::Right || clearing == CSS::ClearAndFloat::Both; }
00379 
00381                 inline void setFloat(const Property floatProp) { floating = floatProp; if (floating == CSS::ClearAndFloat::Both) floating = CSS::ClearAndFloat::None; }
00383                 inline void setClear(const Property clearProp) { clearing = clearProp; }
00384 
00386                 ClearAndFloat(const Property floatProp = CSS::ClearAndFloat::None, const Property clearProp = CSS::ClearAndFloat::None) : floating(floatProp), clearing(clearProp) {}
00387             };
00388 
00390             struct SplitLimit
00391             {
00393                 int32 right;
00395                 int32 left;
00396 
00398                 SplitLimit(const int32 _left = 0, const int32 _right = 0) : left(_left), right(_right) {}
00400                 inline void Reset() { right = left = 0; }
00401             };
00402     
00403 
00405             const BoxSizes      declaredBox;
00407             const Position      declaredPos;
00408         public:
00410             enum ContentType
00411             {
00412                 Text        = 0,    
00413                 Image       = 1,    
00414                 Object      = 2,    
00415                 Input       = 3,    
00416                 TextArea    = 4,    
00417                 Select      = 5,    
00418                 Button      = 6,    
00419                 Table       = 7,    
00420                 Other       = 8,    
00421             }   contentType;
00423             Strings::FastString contentText;
00425             ComputedBoxSizes    computedBox;
00427             ComputedPosition    computedPos;
00429             DisplayMode         displayMode;
00431             SplitLimit          splitLimit;
00432 
00434             bool                leftToRight;
00436             LineHeight          lineHeight;
00438             Font  *             boxFont;
00440             ClearAndFloat       clearAndFloat;
00442             TextAlign *         textAlign;
00444             VerticalAlign *     verticalAlign;
00446             TextDecoration      textDecoration;
00447 
00449             const BoxHierarchy *UID;
00451             Mapper  &           mapper;
00452 
00454             Box *               ancestor;
00456             Box *               container;
00458             Box *               previous;
00460             Box *               next;
00462             Box *               child;
00463 
00465             uint32              iteration;
00466 
00468             inline Box * findFirstChildOf(Box * container) { return container->child; }
00470             inline Box * findLastChildOf(Box * container) { Box * child = container->child; while (child && child->next) child = child->next; return child; }
00471 
00473             bool                renderAsAnonymousBlock;
00474 
00475 
00478             void findContainingBlock()
00479             {
00480                 // 10.1.2 (and 10.1.1 because in that case ancestor is 0)
00481                 if (!declaredPos.absolutelyPositioned())
00482                     container = ancestor;
00483                 else if (declaredPos.type == CSS::Position::Fixed)
00484                     container = mapper.getViewportBox();
00485                 else if (declaredPos.type == CSS::Position::Absolute)
00486                 {
00487                     Box * ancest = ancestor;
00488                     while (ancest)
00489                     {
00490                         if (ancest->declaredPos.type != CSS::Position::Static)   break;
00491                         ancest = ancest->ancestor;
00492                     }
00493                     
00494                     // 10.1.4 is done in the rendering size computation
00495                     container = ancest;
00496                 }
00497             }
00498 
00500             void findFirstBlockContainer()
00501             {
00502                 // 10.1.2 (and 10.1.1 because in that case ancestor is 0)
00503                 Box * ancest = container;
00504                 while (ancest)
00505                 {
00506                     if (ancest->displayedAsBlock())   break;
00507                     ancest = ancest->ancestor;
00508                 }
00509                 
00510                 if (ancest)
00511                 {
00512                     ComputedPosition boxSize;
00513                     ancest->getContentPosition(boxSize);
00514                     splitLimit.left = boxSize.left; splitLimit.right = boxSize.right;
00515                 }
00516             }
00517 
00519             inline uint32 max(const uint32 a, const uint32 b) const { return a > b ? a : b; }
00520 
00536             bool computeRenderingSize(const uint32 currentIteration, const uint32 top = 0)
00537             {
00538                 // Already done
00539                 if (currentIteration <= iteration) return true;
00540                 computedPos.Reset(); computedBox.Reset(); splitLimit.Reset();
00541 
00542                 // Find the container
00543                 findContainingBlock();
00544 
00545                 ComputedPosition boxSize;
00546 
00547                 if (!container)
00548                 {   // We are first container
00549                     boxSize.right = mapper.getViewportWidth();
00550                     boxSize.bottom = mapper.getViewportHeight();
00551                 } else
00552                 {   // Process the size from the container
00553                     container->getContentPosition(boxSize);
00554                     if (declaredPos.type == CSS::Position::Absolute)
00555                     {   // Need to adjust following 10.1.4
00556                         if (container->displayedAsBlock())
00557                         {   // The box is from the padding edge 10.1.4.1
00558                             boxSize.top -= computedBox.padding.top;
00559                             boxSize.left -= computedBox.padding.left;
00560                             boxSize.right += computedBox.padding.right;
00561                             boxSize.bottom += computedBox.padding.bottom;
00562                         } else
00563                         {   // 10.1.4.2
00564                             ComputedPosition firstBox, lastBox;
00565                             Box * first = findFirstChildOf(container);
00566                             Box * last  = findLastChildOf(container);
00567                             if (first && last)
00568                             {
00569                                 first->getContentPosition(firstBox);
00570                                 last->getContentPosition(lastBox);
00571                                 if (container->leftToRight)
00572                                 {   // 10.1.4.2.1
00573                                     boxSize.top = firstBox.top;
00574                                     boxSize.left = firstBox.left;
00575                                     boxSize.right = lastBox.right;
00576                                     boxSize.bottom = lastBox.bottom;
00577                                 } else 
00578                                 {   // 10.1.4.2.2
00579                                     boxSize.top = firstBox.top;
00580                                     boxSize.right = firstBox.right;
00581                                     boxSize.left = lastBox.left;
00582                                     boxSize.bottom = lastBox.bottom;
00583                                 }
00584                             }
00585                         }
00586                     }
00587                 }
00588 
00589                 // If we are not displayed, well, don't display, but save the found box size
00590                 if (displayMode == CSS::DisplayMode::None) { computedPos = boxSize; computedPos.right = boxSize.left; computedPos.bottom = boxSize.top; iteration = currentIteration; return true; }
00591 
00592 
00593                 // Is this box displayed as block ?
00594                 bool isBlock = displayedAsBlock() || isFloating();
00595 
00596                 // Check if the box if floating (float property is set and the box is a replaced content or its width is set)
00597                 if (isFloating())
00598                 {   // The box is floating
00599                     // We have to remove it from the normal flow
00600                     zeroIfAuto(declaredPos.left);
00601                     zeroIfAuto(declaredPos.right);
00602                     zeroIfAuto(declaredBox.margin.left);
00603                     zeroIfAuto(declaredBox.margin.right);
00604                     uint32 width = (declaredBox.content.width && !declaredBox.content.width->isAuto()) ? declaredBox.content.getWidth(currentIteration) : (replacedElement() ? getReplacedWidth() : mapper.getRenderedWidthOf(this));
00605 
00606                     // 10.6.2
00607                     zeroIfAuto(declaredPos.top);
00608                     zeroIfAuto(declaredPos.bottom);
00609                     zeroIfAuto(declaredBox.margin.top);
00610                     zeroIfAuto(declaredBox.margin.bottom);
00611                     uint32 height = (declaredBox.content.height && !declaredBox.content.height->isAuto()) ? declaredBox.content.getHeight(currentIteration) : (replacedElement() ? getReplacedHeight() : mapper.getRenderedHeightOf(this));
00612 
00613                     computedPos.top = boxSize.top;
00614                     computedPos.bottom = boxSize.top + height + declaredBox.padding.getHeight(currentIteration) + declaredBox.border.getHeight(currentIteration) + declaredBox.margin.getHeight(currentIteration); 
00615 
00616                     if (clearAndFloat.getFloat() == CSS::ClearAndFloat::Left)
00617                     {
00618                         // If any element already floating on the left is get from here
00619                         computedPos.left = mapper.getFloatLeft(container);
00620                         computedPos.right = boxSize.left + width + declaredBox.padding.getWidth(currentIteration) + declaredBox.border.getWidth(currentIteration) + declaredBox.margin.getWidth(currentIteration); 
00621                     } else
00622                     {
00623                         // If any element already floating on the right is get from here
00624                         computedPos.right = mapper.getFloatRight(container);
00625                         computedPos.left = boxSize.right - (width + declaredBox.padding.getWidth(currentIteration) + declaredBox.border.getWidth(currentIteration) + declaredBox.margin.getWidth(currentIteration)); 
00626                     }
00627 
00628                     transferDeclaredValues(false);
00629                     computedBox.content.width = width;
00630                     computedBox.content.height = height;
00631                     setComputedValues();
00632                 } else
00633                 {
00634                     // 9.2.1
00635                     bool shouldBeSeenAsBlock = mapper.shouldBeSeenAsBlock(this);
00636                     if (!isBlock && !replacedElement() && shouldBeSeenAsBlock) 
00637                     {
00638                         displayMode = CSS::DisplayMode::Block;
00639                         isBlock = true;
00640                     }
00641 
00642                     Box * previousBox = previous;
00643 
00644                     // Now we have the box position and size, let's compute the other dimensions
00645                     // Adjust the width if required (it's required for block element and non replaced element) 
00646                     // see also http://www.w3.org/TR/REC-CSS2/visudet.html#Computing_widths_and_margins
00647                     if (isBlock /*|| replacedElement()*/)
00648                     {
00649                         // http://www.w3.org/TR/REC-CSS2/visuren.html 
00650                         // Paragraph 9.4
00651                         while (previousBox && previousBox->displayMode == CSS::DisplayMode::None) previousBox = previousBox->previous;
00652                         // Check the previous child if it is a block
00653                         if (previousBox && previousBox->displayedAsBlock())
00654                         {
00655                             // 9.4.1
00656                             // It's the case, so this box should be vertical aligned after the previous box
00657                             // However, our top margin need to collapse with the previous block
00658                             uint32 topMargin = max(previousBox->computedBox.margin.bottom, (declaredBox.margin.top && !declaredBox.margin.top->isAuto()) ? declaredBox.margin.getTopWidth(currentIteration) : 0);
00659                             computedPos.top = previousBox->computedPos.bottom - previousBox->computedBox.margin.bottom + topMargin;
00660                             computedPos.left = boxSize.left; 
00661                             computedPos.right = boxSize.right;
00662                             computedPos.bottom = boxSize.bottom;
00663                         } else if (previousBox)
00664                         {
00665                             // 9.4.2, Inline boxes
00666                             // We are a block after some inline boxes, so we will adjust both our left edge and top edge
00667 
00668                             // 9.2.1, we need to stack vertically from container left edge, and our top set to previous bottom
00669                             computedPos.left = boxSize.left; computedPos.right = boxSize.right;
00670                             computedPos.top = previousBox->computedPos.bottom;
00671                             computedPos.bottom = boxSize.bottom;
00672                         } else
00673                         {
00674                             computedPos.top = boxSize.top;
00675                             computedPos.left = boxSize.left; 
00676                             computedPos.right = boxSize.right;
00677                             computedPos.bottom = boxSize.bottom;
00678                         }
00679 
00680                         // Ok, the right and bottom will be deduced later on
00681 /*
00682                         // If the width is not set (so it is defined or deduced as "auto"), then the final width is the boxSize width
00683                         
00684                         if (!declaredBox.content.width || declaredBox.content.width->isAuto())     
00685                         {       computedPos.right = replacedElement() ? getReplacedWidth() : boxSize.right;  } 
00686                         else    computedPos.right = declaredBox.content.getWidth(currentIteration); 
00687                         if (!declaredBox.content.height || declaredBox.content.height->isAuto())    
00688                         {       computedPos.bottom = replacedElement() ? getReplacedHeight() : boxSize.bottom;  } 
00689                         else    computedPos.bottom = declaredBox.content.getHeight(currentIteration);
00690 
00691 
00692 */
00693                     } else 
00694                     {   // Inline boxes
00695                         if (!mapper.areFloatBoxInContainer(container))
00696                         {
00697                             // 9.4.2, Inline box
00698                             // Check the previous box
00699                             if (previousBox)
00700                             {
00701                                 // The previous was a block ?
00702                                 if (previousBox->displayedAsBlock())
00703                                 {   // Yes, ok, start on a new line below
00704                                     computedPos.top = previousBox->computedPos.bottom;
00705                                     computedPos.left = boxSize.left;
00706                                 } else
00707                                 {   // No ? So try to fit on the right
00708                                     computedPos.top = previousBox->computedPos.bottom 
00709                                                         - previousBox->computedBox.padding.bottom 
00710                                                         - previousBox->computedBox.border.bottom 
00711                                                         - previousBox->computedBox.margin.bottom 
00712                                                         - (previousBox->replacedElement() ? previousBox->computedBox.content.getHeight() : previousBox->lineHeight.getHeightInPixels(previousBox->boxFont, currentIteration));
00713                                     computedPos.left = previousBox->computedPos.right;
00714                                 }
00715                             } else
00716                             {
00717                                 computedPos.top = boxSize.top;
00718                                 computedPos.left = boxSize.left;
00719                             } 
00720                             computedPos.right = boxSize.right;
00721                             computedPos.bottom = boxSize.bottom;
00722 
00723                         } else
00724                         {   // Check if the box is clear from one size?
00725                             computedPos.right = boxSize.right;
00726                             computedPos.bottom = boxSize.bottom;
00727 
00728                             bool shiftDown = false;
00729                             if (!clearAndFloat.isClearFromLeft())     computedPos.left = mapper.getFloatLeft(container);
00730                             else shiftDown = true;
00731                             if (!clearAndFloat.isClearFromRight())    computedPos.right = mapper.getFloatRight(container);
00732                             else shiftDown = true;
00733                             if (shiftDown)                            computedPos.top = mapper.getFloatBottom(container);
00734                             else 
00735                             {
00736                                 // 9.4.2, Inline box
00737                                 // Check the previous box
00738                                 if (previous)
00739                                 {
00740                                     // The previous was a block, so try to fit on the right
00741                                     computedPos.top = previousBox->computedPos.bottom - previousBox->computedBox.padding.bottom - previousBox->computedBox.border.bottom - previousBox->computedBox.margin.bottom - previousBox->lineHeight.getHeightInPixels(previousBox->boxFont, currentIteration);;
00742                                     computedPos.left = previousBox->computedPos.right;
00743                                 } else
00744                                 {
00745                                     computedPos.top = boxSize.top;
00746                                     computedPos.left = boxSize.left;
00747                                 }
00748                             }
00749                         }
00750                     }
00751 
00752                     // Now compute the width and height attribute value
00753                     // Let's apply 10.3.1 and 10.3.2
00754                     uint32 width = computedPos.right - computedPos.left;
00755                     uint32 height = computedPos.bottom - computedPos.top;
00756 
00757                     // Check if this box is a table 
00758                     if (contentType == Table)
00759                     {
00760                         // It is, so need to apply http://www.w3.org/TR/html4/appendix/notes.html#notes-tables
00761                         // Get the table layout 
00762                         TableLayout * tableLayout = mapper.getTableLayout(this);
00763                         if (tableLayout)
00764                         {   // Found
00765                             // Compute the table minimum and maximum width
00766                             int32 previousMaxWidth = 0;
00767                             computeTableWidths(0, previousMaxWidth);
00768                             // Let's apply 10.3.3 and 10.3.4
00769                             zeroIfAuto(declaredPos.left);
00770                             zeroIfAuto(declaredPos.right);
00771                             // Let's try with the maximum size
00772                             //computedPos.right = boxSize.right;
00773                             solveBlockLevelWidth(boxSize.right - boxSize.left);
00774                             // Let's apply 10.6.3
00775                             zeroIfAuto(declaredPos.top);
00776                             zeroIfAuto(declaredPos.bottom);
00777                             zeroIfAuto(declaredBox.margin.top);
00778                             zeroIfAuto(declaredBox.margin.bottom);
00779 
00780                             transferDeclaredValues(false);
00781 
00782                             uint32 bottom = 0;
00783 
00784                             // Then, there are 3 possible cases.
00785                             if (tableLayout->minimumWidth > width)
00786                             {
00787                                 // Case 1, the table minimum required width is larger than the available space, we need to allow horizontal scrolling
00789                                 // And assign minimum width to the table, and all its columns/cells 
00790                                 assignWidthToTable(0, tableLayout, currentIteration, width, bottom);
00791                             } else if (tableLayout->maximumWidth <= width)
00792                             {   // Case 2, the table can enter the available space without any problem, so we assign the maximum width
00793                                 assignWidthToTable(1, tableLayout, currentIteration, width, bottom);
00794                             } else
00795                             {   // Last case, we need to assign the available width
00796                                 assignWidthToTable(2, tableLayout, currentIteration, width, bottom);
00797                             }
00798 
00799                             declaredBox.content.width->setComputedValue(width, currentIteration);
00800                             declaredBox.content.height->setComputedValue(bottom - computedPos.top, currentIteration);
00801                             computedBox.content.height = bottom - computedPos.top;
00802                             computedBox.content.width = width;
00803 
00804                             // Ok, save the right and bottom position
00805                             computedPos.right = computedPos.left + getBlockWidth();
00806                             computedPos.bottom = computedPos.top + getBlockHeight();
00807                         }
00808                         else
00809                         {
00810                             // Not found ? (it's clearly an error)
00811                             return false;
00812                         }
00813                         // Well, it's done!
00814                         iteration = currentIteration; 
00815                         return true;
00816                     } 
00817 
00818                     if (!isBlock)
00819                     {
00820                         // Not a containing block, so width is ignored here
00821                         zeroIfAuto(declaredPos.left);
00822                         zeroIfAuto(declaredPos.right);
00823                         zeroIfAuto(declaredBox.margin.left);
00824                         zeroIfAuto(declaredBox.margin.right);
00825 
00826                         zeroIfAuto(declaredPos.top);
00827                         zeroIfAuto(declaredPos.bottom);
00828                         zeroIfAuto(declaredBox.margin.top);
00829                         zeroIfAuto(declaredBox.margin.bottom);
00830 
00831                         // In all case, we need to transfer the declared value to the computed value
00832                         transferDeclaredValues(false);
00833 
00834                         if (replacedElement())
00835                         {   // Set the replaced width
00836                             if (declaredBox.content.width)  computedBox.content.width = declaredBox.content.width->isAuto() ? getReplacedWidth() : declaredBox.content.width->getAsPixels(currentIteration);
00837                             else                            computedBox.content.width = mapper.getMinimumWidthOf(this);
00838                             
00839                             // 10.6.2
00840                             if (declaredBox.content.height) computedBox.content.height = declaredBox.content.height->isAuto() ? getReplacedHeight() : declaredBox.content.height->getAsPixels(currentIteration);
00841                             else                            computedBox.content.height = mapper.getMinimumHeightOf(this);
00842                         } else
00843                         {
00844                             // Check if we have any child
00845                             if (child)
00846                             {
00847                                 // Inline box shouldn't have any child, but we still need to handle children on illegal documents
00848                                 uint32 top, bottom, left, right;
00849                                 // Children are only inline box
00850                                 top = mapper.findTopChildrenPos(this, false);
00851                                 bottom = mapper.findBottomChildrenPos(this, false);                                
00852                                 left = mapper.findLeftChildrenPos(this, false);
00853                                 right = mapper.findRightChildrenPos(this, false);
00854 
00855                                 // Then set the values
00856                                 if (declaredBox.content.height) declaredBox.content.height->setComputedValue(bottom - top, currentIteration);
00857                                 computedBox.content.height = bottom - top;
00858                                 if (declaredBox.content.width) declaredBox.content.width->setComputedValue(right - left, currentIteration);
00859                                 computedBox.content.width = right - left;
00860                             } else 
00861                             {
00862                                 // Set the height from the line height
00863                                 computedBox.content.height = lineHeight.getHeightInPixels(boxFont, currentIteration);
00864                                 lineHeight.setComputedValue(computedBox.content.height, currentIteration);
00865                             
00866                                 // Then store the result in the computed box
00867                                 // Need to find the width from the element itself, and it depends on the rendering...
00868                                 // So we will set the minimal width depending on the renderer, so the mapper will know if it can make 
00869                                 // the block enter this
00870                                 uint32 minWidth = mapper.getMinimumWidthOf(this);
00871                                 // Check if the minimum width can enter in the containing box
00872                                 if (minWidth + ((uint32)(declaredBox.border.getWidth(currentIteration) + declaredBox.margin.getWidth(currentIteration) + declaredBox.padding.getWidth(currentIteration)))> (uint32)(boxSize.right - computedPos.left))
00873                                 {   // We need to be split
00874                                     // So set the size we have
00875                                     computedBox.content.width = boxSize.right - boxSize.left;
00876                                     setComputedValues();
00877                                     // Ask the renderer to give the right border position after the split
00878                                     splitLimit.right = boxSize.right; splitLimit.left = boxSize.left;
00879                                     // Need to adjust the split limit from the first container that is displayed as block
00880                                     // In good documents, it should be the current container (as inline element shouldn't have children)
00881                                     // but, it's too frequent to have documents that don't validate this rule
00882                                     findFirstBlockContainer();
00883                                     mapper.getSplitLimitsOf(this, splitLimit.left, splitLimit.right, computedPos.top, computedPos.left, computedPos.right, computedPos.bottom);
00884                                     computedBox.content.height = computedPos.bottom - computedPos.top;
00885 
00886                                     // Ok, save the right and bottom position
00887                                     iteration = currentIteration; 
00888                                     return true;
00889                                 } // Else
00890                                 {
00891                                     computedBox.content.width = minWidth;
00892                                 }
00893                             }
00894                             
00895                         }
00896 
00897                         setComputedValues();
00898                         computedPos.right = computedPos.left + getBlockWidth();
00899                         computedPos.bottom = computedPos.top + getBlockHeight();
00900                     } else if (isBlock)
00901                     {   
00902                         if (!declaredPos.absolutelyPositioned())
00903                         {
00904                             // Let's apply 10.3.3 and 10.3.4
00905                             zeroIfAuto(declaredPos.left);
00906                             zeroIfAuto(declaredPos.right);
00907                             // Let's try with the maximum size
00908                             //computedPos.right = boxSize.right;
00909                             solveBlockLevelWidth(boxSize.right - boxSize.left);
00910 
00911                             // Let's apply 10.6.3
00912                             zeroIfAuto(declaredPos.top);
00913                             zeroIfAuto(declaredPos.bottom);
00914                             zeroIfAuto(declaredBox.margin.top);
00915                             zeroIfAuto(declaredBox.margin.bottom);
00916 
00917                             transferDeclaredValues(false);
00918 
00919                             if (declaredBox.content.height && declaredBox.content.height->isAuto())
00920                             {
00921                                 uint32 top = 0, bottom = 0;
00922                                 if (replacedElement())
00923                                 {
00924                                     // 10.6.2
00925                                     bottom = getReplacedHeight();
00926                                 } else
00927                                 {
00928                                     // Does the block have block level children ?
00929                                     if (mapper.hasBlockLevelChildren(this))
00930                                     {   // This is very difficult here, as we need to compute the child box size in order to compute our height
00931                                         // So we are reversing the recurrence 
00932                                         top = computedPos.top; //mapper.findTopChildrenPos(this, true);
00933                                         bottom = mapper.findBottomChildrenPos(this, true);
00934                                     } else
00935                                     {   // Children are only inline box
00936                                         top = mapper.findTopChildrenPos(this, false);
00937                                         bottom = mapper.findBottomChildrenPos(this, false);
00938                                     }
00939                                 }
00940                                 declaredBox.content.height->setComputedValue(bottom - top, currentIteration);
00941                                 computedBox.content.height = bottom - top;
00942                             } else 
00943                             {
00944                                 computedBox.content.height = declaredBox.content.height ? declaredBox.content.height->getAsPixels(currentIteration) : 0;
00945                             }
00946 
00947                             // Ok, save the right and bottom position
00948                             computedPos.right = computedPos.left + getBlockWidth();
00949                             computedPos.bottom = computedPos.top + getBlockHeight();
00950                         } else 
00951                             solveAbsoluteBlockLevelWidth(boxSize.right - boxSize.left);
00952 
00953 
00954                     }
00955                 }
00956 
00957                 // Well, it's done!
00958                 iteration = currentIteration; 
00959                 return true;
00960             }
00961             
00963             inline uint32 getWidthFromConstraint(const uint32 type, TableLayout::Column & col, const int32 availableWidthLessTableMinWidth, const int32 maxWidthLessMinWidth)
00964             {
00965                 switch(type)
00966                 {
00967                     // Minimum width
00968                 case 0:
00969                     return col.minimumWidth;
00970                     // Maximum width
00971                 case 1:
00972                     return col.maximumWidth;
00973                     // Proportional width
00974                 case 2:
00975                     {
00976                         int32 d = (int32)col.maximumWidth - (int32)col.minimumWidth;
00977                         return (uint32) ((int32)col.minimumWidth 
00978                                             + (d * availableWidthLessTableMinWidth + (maxWidthLessMinWidth>>1))/maxWidthLessMinWidth); 
00979                     }
00980                 default: 
00981                     return 0;
00982                 }
00983             }
00984 
00985 
00987             inline uint32 computeHeightFromAvailableWidth(const uint32 width, const uint32 currentIteration)
00988             {
00989                 // Check for tables
00990                 if (UID && UID->isTaggedAs(GenericElement::TABLE))
00991                 {
00992                     // It's a table, so we need to apply this width to the table (recursing algorithm), in order to get its height
00993                     // It is, so need to apply http://www.w3.org/TR/html4/appendix/notes.html#notes-tables
00994                     // Get the table layout 
00995                     TableLayout * tableLayout = mapper.getTableLayout(this);
00996                     uint32 bottom = 0;
00997                     if (tableLayout)
00998                     {   // Found
00999                         if (width < tableLayout->minimumWidth)
01000                             assignWidthToTable(0, tableLayout, currentIteration, width, bottom);
01001                         else if (width > tableLayout->maximumWidth)
01002                             assignWidthToTable(1, tableLayout, currentIteration, width, bottom);
01003                         else
01004                             assignWidthToTable(2, tableLayout, currentIteration, width, bottom);
01005                     }
01006                     return bottom;
01007                 } 
01008                 
01009                 bool isBlock = displayedAsBlock();
01010                 if (!isBlock)
01011                 {
01012                     if (replacedElement())
01013                     {
01014                         if (declaredBox.content.height) return declaredBox.content.height->isAuto() ? getReplacedHeight() : declaredBox.content.height->getAsPixels(currentIteration);
01015                         else                            return mapper.getMinimumHeightOf(this);
01016                     }                        
01017                     else 
01018                     {
01019                         if (child)
01020                         {
01021                             // Inline box shouldn't have any child, but we still need to handle children on illegal documents
01022                             uint32 top, bottom;
01023                             // Children are only inline box
01024                             top = mapper.findTopChildrenPos(this, false, false);
01025                             bottom = mapper.findBottomChildrenPos(this, false, false);
01026                             //computedPos = oldPos;
01027                             return bottom - top;
01028                         }
01029                         else
01030                         {
01031                             uint32 minHeight = lineHeight.getHeightInPixels(boxFont, currentIteration);
01032                             uint32 minWidth = mapper.getMinimumWidthOf(this);
01033                             // Check if the minimum width can enter in the containing box
01034                             if (minWidth + ((uint32)(declaredBox.border.getWidth(currentIteration) + declaredBox.margin.getWidth(currentIteration) + declaredBox.padding.getWidth(currentIteration)))> width)
01035                             {   // We need to be split
01036                                 // So set the size we have
01037                                 computedBox.content.width = width;
01038                                 setComputedValues();
01039                                 // Ask the renderer to give the right border position after the split
01040                                 splitLimit.right = width; splitLimit.left = 0;
01041                                 // Need to adjust the split limit from the first container that is displayed as block
01042                                 // In good documents, it should be the current container (as inline element shouldn't have children)
01043                                 // but, it's too frequent to have documents that don't validate this rule
01044                                 findFirstBlockContainer();
01045                                 mapper.getSplitLimitsOf(this, splitLimit.left, splitLimit.right, computedPos.top, computedPos.left, computedPos.right, computedPos.bottom);
01046                                 minHeight = computedPos.bottom - computedPos.top;
01047                             }
01048                             return minHeight;
01049                         }
01050                     }
01051                 } else
01052                 {
01053                     if (!declaredPos.absolutelyPositioned())
01054                     {
01055                         if (declaredBox.content.height && declaredBox.content.height->isAuto())
01056                         {
01057                             uint32 top = 0, bottom = 0;
01058                             if (replacedElement())
01059                             {
01060                                 // 10.6.2
01061                                 bottom = getReplacedHeight();
01062                             } else
01063                             {
01064                                 // Does the block have block level children ?
01065                                 if (mapper.hasBlockLevelChildren(this))
01066                                 {   // This is very difficult here, as we need to compute the child box size in order to compute our height
01067                                     // So we are reversing the recurrence 
01068                                     top = computedPos.top; 
01069                                     bottom = mapper.findBottomChildrenPos(this, true, false);
01070                                 } else
01071                                 {   // Children are only inline boxes (easier to compute)
01072                                     top = mapper.findTopChildrenPos(this, false, false);
01073                                     bottom = mapper.findBottomChildrenPos(this, false, false);
01074                                 }
01075                             }
01076                             return bottom - top;
01077                         } else 
01078                         {
01079                             return declaredBox.content.height ? declaredBox.content.height->getAsPixels(currentIteration) : 0;
01080                         }
01081                     }
01082                 }
01083                 return 0;
01084             }
01085 
01087             inline void assignWidthToTable(const uint32 type, TableLayout * tableLayout, const uint32 currentIteration, const uint32 width, uint32 & bottom)
01088             {
01089                 if (tableLayout)
01090                 {
01091                     uint32 maxColumn = tableLayout->realColumnCount();
01092                     uint32 xOffset = 0, yOffset = 0;
01093                     const int32 availableWidthLessTableMinWidth = (int32)width - (int32)tableLayout->minimumWidth;
01094                     const int32 maxWidthLessMinWidth = (int32)tableLayout->maximumWidth - (int32)tableLayout->minimumWidth;
01095 
01096                     // First pass, find the row height for unspanned cells
01097                     Container::PlainOldData<uint32>::Array rowHeights;
01098                     uint32 i = 0;
01099                     for (; i < tableLayout->rowCount(); i++)
01100                     {
01101                         uint32 rowHeight = 0;
01102                         uint32 j = 0;
01103                         for (; j < maxColumn;) // Iteration is done in the loop
01104                         {
01105                             uint32 cellWidth = getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j), availableWidthLessTableMinWidth, maxWidthLessMinWidth);
01106                             TableLayout::Cell * cell = tableLayout->findCellAt(i, j);
01107                             if (!cell) break;
01108                             for (uint32 z = 1; z < cell->horizontalSpan; z++)
01109                                 cellWidth += getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j+z), availableWidthLessTableMinWidth, maxWidthLessMinWidth); 
01110                             j += cell->horizontalSpan;
01111                             if (cell->verticalSpan > 1) continue;
01112                             // Get the box for this cell
01113                             Box * box = (Box*)cell->userData2;
01114                             if (!box) continue; // No renderered content, as the cell is missing
01115                             if (box->iteration >= currentIteration) continue;
01116                             // Need to compute its height, only knowing its width
01117                             box->computedPos.right = box->computedPos.left + cellWidth;
01118                             uint32 height = box->computeHeightFromAvailableWidth(cellWidth, currentIteration);
01119                             if (height > rowHeight) rowHeight = height;
01120                         }
01121                         rowHeights.Append(rowHeight);
01122                     }
01123 
01124                     // Second pass, fix the height for spanned cells
01125                     for (i = 0; i < tableLayout->rowCount(); i++)
01126                     {
01127                         xOffset = 0;
01128                         uint32 rowHeight = 0;
01129                         uint32 j = 0;
01130                         for (; j < maxColumn;) // Iteration is done in the loop
01131                         {
01132                             uint32 cellWidth = getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j), availableWidthLessTableMinWidth, maxWidthLessMinWidth);
01133                             TableLayout::Cell * cell = tableLayout->findCellAt(i, j);
01134                             if (!cell) break;
01135                             uint32 z = 1;
01136                             for (; z < cell->horizontalSpan; z++)
01137                                 cellWidth += getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j+z), availableWidthLessTableMinWidth, maxWidthLessMinWidth); 
01138                             xOffset += cellWidth;
01139                             j += cell->horizontalSpan;
01140                             if (cell->verticalSpan <= 1) continue;
01141                             // Get the box for this cell
01142                             Box * box = (Box*)cell->userData2;
01143                             if (!box) continue; // No renderered content, as the cell is missing
01144                             if (box->iteration >= currentIteration) continue;
01145                             // Need to compute its height, only knowing its width
01146                             uint32 height = box->computeHeightFromAvailableWidth(cellWidth, currentIteration);
01147                             // Add available heights to fit the span
01148                             rowHeight = 0;
01149                             for (z = 0; z < cell->verticalSpan; z++)
01150                                 rowHeight += rowHeights[i+z];
01151 
01152                             if (height > rowHeight) 
01153                             {
01154                                 // Ok, we need to distribute the missing space evenly on every row (no proportional distribution here)
01155                                 uint32 diff = height - rowHeight;
01156                                 for (z = 0; z < cell->verticalSpan; z++)
01157                                     rowHeights[i+z] += diff / cell->verticalSpan;
01158                             }
01159                         }
01160                     }
01161 
01162                     // Last past, assign the position to cells
01163                     for (i = 0; i < tableLayout->rowCount(); i++)
01164                     {
01165                         xOffset = 0;
01166                         for (uint32 j = 0; j < maxColumn; )
01167                         {
01168                             uint32 cellWidth = getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j), availableWidthLessTableMinWidth, maxWidthLessMinWidth);
01169                             TableLayout::Cell * cell = tableLayout->findCellAt(i, j);
01170                             if (!cell) break;
01171                             uint32 z = 1;
01172                             for (; z < cell->horizontalSpan; z++)
01173                                 cellWidth += getWidthFromConstraint(type, tableLayout->unsafeColumnAt(j+z), availableWidthLessTableMinWidth, maxWidthLessMinWidth); 
01174                             j += cell->horizontalSpan;
01175                             // Get the box for this cell
01176                             Box * box = (Box*)cell->userData2;
01177                             if (!box) continue; // No renderered content, as the cell is missing
01178                             if (box->iteration < currentIteration) 
01179                             {
01180                                 box->transferDeclaredValues(false);
01181                                 // Need to compute its height, only knowing its width
01182                                 box->computedPos.top = computedPos.top + yOffset;
01183                                 box->computedPos.left = computedPos.left + xOffset;
01184                                 box->computedPos.right = box->computedPos.left + cellWidth;
01185 
01186                                 box->computedBox.content.width = cellWidth;
01187                                 uint32 rowHeight = 0;
01188                                 for (z = 0; z < cell->verticalSpan; z++)
01189                                     rowHeight += rowHeights[i+z];
01190                                 box->computedPos.bottom = box->computedPos.top + rowHeight;
01191                                 box->computedBox.content.height = rowHeight;
01192 
01193                                 box->iteration = currentIteration;
01194                             }
01195                             xOffset += cellWidth;
01196                         }
01197                         yOffset += rowHeights[i];
01198                     }
01199                     bottom = computedPos.top + yOffset;
01200                 }
01201             }
01202 
01204             inline void computeTableWidths(TableLayout::Cell * cellPtr, int32 & previousMaxWidth)
01205             {
01206                 // Ok, then compute the minimum and maximum size for this box, if it's possible
01207                 int32 minimumWidth = 0, maximumWidth = 0;
01208 
01209                 // Make sure this box is a cell
01210                 if (UID && UID->isTaggedAs(GenericElement::TABLE))
01211                 {
01212                     // It's a table, let's handle it differently
01213                     // It is, so need to apply http://www.w3.org/TR/html4/appendix/notes.html#notes-tables
01214                     // Get the table layout 
01215                     TableLayout * tableLayout = mapper.getTableLayout(this);
01216                     if (tableLayout)
01217                     {   // Found
01218                         // Then, for each cell, compute the min and max width
01219                         uint32 i = 0;
01220                         for (i = 0; i < tableLayout->rowCount(); i++)
01221                         {
01222                             TableLayout::Row & row = (*tableLayout)[i];
01223                             for (uint32 j = 0; j < row.cellCount(); j++)
01224                             {
01225                                 TableLayout::Cell & currentCell = row[j];
01226                                 // Extract the associated box
01227                                 Box * cellBox = (Box*)currentCell.userData2;
01228                                 // Compute and store table widths
01229                                 if (cellBox) 
01230                                 {
01231                                     currentCell.minimumWidth = currentCell.maximumWidth = 0;
01232                                     int32 previousMaxWidth2 = 0;
01233                                     cellBox->computeTableWidths(&currentCell, previousMaxWidth2);
01234                                 }
01235                             }
01236                         }
01237 
01238                         // Done, so then, compute column sizes
01241                         uint32 maxColumn = tableLayout->realColumnCount();
01242                         // For each column, we have to determine the minimum and maximum size, excluding spanned cells
01243                         for (i = 0; i < maxColumn; i++)
01244                         {
01245                             // Get the column reference
01246                             TableLayout::Column & col = tableLayout->unsafeColumnAt(i);
01247                             col.minimumWidth = 0; col.maximumWidth = 0;
01248                             for (uint32 j = 0; j < tableLayout->rowCount(); j++)
01249                             {
01250                                 TableLayout::Cell * currentCell = tableLayout->findCellAt(j, i);
01251                                 if (!currentCell) break;
01252                                 if (currentCell->horizontalSpan > 1) continue;
01253                                 if (currentCell->minimumWidth > col.minimumWidth) col.minimumWidth = currentCell->minimumWidth;
01254                                 if (currentCell->maximumWidth > col.maximumWidth) col.maximumWidth = currentCell->maximumWidth;
01255                             }
01256                         }
01257 
01258                         // Then, we rerun the algorithm, but this time only for spanned cells
01259                         // Based on minimum-width ratio, we either accept the column width, or reprocess it from spanned cells
01260                         // Trying to respect the ratio of the previous widths
01261                         for (i = 0; i < tableLayout->rowCount(); i++)
01262                         {
01263                             for (uint32 j = 0; j < maxColumn; j++)
01264                             {
01265                                 TableLayout::Cell * currentCell = tableLayout->findCellAt(i, j);
01266                                 if (!currentCell) break;
01267                                 if (currentCell->horizontalSpan <= 1) continue;
01268 
01269                                 // Ok, make sure the spanned cell fits in the columns it spans onto
01270                                 uint32 sumMinWidth = 0;
01271                                 uint32 sumMaxWidth = 0;
01272                                 // Need to find the columns on which this cell spans
01273                                 uint32 z = 0;
01274                                 for (; z < currentCell->horizontalSpan; z++)
01275                                 {
01276                                     sumMinWidth += tableLayout->unsafeColumnAt(j+z).minimumWidth;
01277                                     sumMaxWidth += tableLayout->unsafeColumnAt(j+z).maximumWidth;
01278                                 }
01279 
01280                                 if (sumMinWidth < currentCell->minimumWidth)
01281                                 {
01282                                     // For each column, let's adapt the minimum width
01283                                     // Width of all column onto which this cell spans over isn't large enough for this cell
01284                                     // We need to proportionally increase every over column
01285                                     uint32 missingWidth = currentCell->minimumWidth - sumMinWidth;
01286                                     for (z = 0; z < currentCell->horizontalSpan; z++)
01287                                     {
01288                                         uint32 & width = tableLayout->unsafeColumnAt(i+z).minimumWidth;
01289                                         width += sumMinWidth ? (missingWidth * width + (sumMinWidth >> 1)) / sumMinWidth : missingWidth / currentCell->horizontalSpan;
01290                                     }
01291                                 }
01292 
01293                                 if (sumMaxWidth < currentCell->maximumWidth)
01294                                 {
01295                                     // Width of all column onto which this cell spans over isn't large enough for this cell
01296                                     // We need to proportionally increase every over column
01297                                     uint32 missingWidth = currentCell->maximumWidth - sumMaxWidth;
01298                                     for (z = 0; z < currentCell->horizontalSpan; z++)
01299                                     {
01300                                         uint32 & width = tableLayout->unsafeColumnAt(i+z).maximumWidth;
01301                                         width += sumMaxWidth ? (missingWidth * width + (sumMaxWidth >> 1)) / sumMaxWidth : missingWidth / currentCell->horizontalSpan;
01302                                     }
01303                                 }
01304 
01305                                 // Ignore all the remaining columns
01306                                 j += currentCell->horizontalSpan - 1;
01307                             }
01308                         }
01309 
01310                         // Ok, great, we now have column range, let's compute table range
01311                         tableLayout->minimumWidth = tableLayout->maximumWidth = 0;
01312                         for (i = 0; i < maxColumn; i++)
01313                         {
01314                             // Get the column reference
01315                             TableLayout::Column & col = tableLayout->unsafeColumnAt(i);
01317                             tableLayout->minimumWidth += col.minimumWidth;
01318                             tableLayout->maximumWidth += col.maximumWidth;
01319                         }
01320 
01321                         // We are done!
01322                         minimumWidth = tableLayout->minimumWidth;
01323                         maximumWidth = tableLayout->maximumWidth + previousMaxWidth;
01324                     }
01325 
01326                 } else if (UID && UID->isTaggedAs(GenericElement::BR))
01327                 {
01328                     previousMaxWidth = 0;
01329                     minimumWidth = maximumWidth = 0;
01330                 } else
01331                 {
01332                     // First start by our own widths
01333                     mapper.getWidthsOf(this, minimumWidth, maximumWidth);
01334                 }
01335 
01336                 if (cellPtr)
01337                 {
01338                     if (((const DOM::Element*)cellPtr->userData)->hasAttribute("NOWRAP"))
01339                     {
01340                         // No text splitting is allowed, so make sure the minimum width is the maximum width
01341                         minimumWidth = maximumWidth;
01342                     }
01343                     // Adjust with those of the cell
01344                     if (cellPtr->minimumWidth < (uint32)minimumWidth) cellPtr->minimumWidth = minimumWidth;
01345                     // If the previous box was an inline box, then we need to add the maximum widths, with the previous one
01346                     if (previous)
01347                     {
01348                         // Is the previous block an inline element like this one
01349                         if (previous->displayedAsInline() && displayedAsInline())
01350                         {
01351                             previousMaxWidth += maximumWidth;
01352                             maximumWidth = previousMaxWidth;
01353                         } else
01354                         {   // Any other case, means restarting from the left part
01355                             previousMaxWidth = 0;
01356                         }
01357                     } else if (displayedAsInline()) previousMaxWidth += maximumWidth;
01358                     if (cellPtr->maximumWidth < (uint32)maximumWidth) cellPtr->maximumWidth = maximumWidth;
01359                     if (previousMaxWidth > (int32)cellPtr->maximumWidth)   cellPtr->maximumWidth = previousMaxWidth;
01360                 
01361                     // Then, iterate over all siblings at this level
01362                     // The algorithm is recursive, here, there is no other way to compute this
01363                     // However, recursion is limited to one pass only other all remaining elements
01364                     if (child)
01365                         child->computeTableWidths(cellPtr, previousMaxWidth);
01366                     // Goes on the next child, only if it is still the same element
01367                     if (next && (next->previous != (Box*)cellPtr->userData2)) // Avoid going on the next cell
01368                         next->computeTableWidths(cellPtr, previousMaxWidth);
01369                 }
01370             }
01371 
01373             inline void transferWidthDeclaredValues(bool content = true, bool marginLeft = true, bool marginRight = true, bool borderLeft = true, bool borderRight = true, bool paddingLeft = true, bool paddingRight = true)
01374             {
01375                 if (content) computedBox.content.width = declaredBox.content.getWidth(mapper.getCurrentIteration());
01376                 if (borderLeft) computedBox.border.left = declaredBox.border.getLeftWidth(mapper.getCurrentIteration());
01377                 if (borderRight) computedBox.border.right = declaredBox.border.getRightWidth(mapper.getCurrentIteration());
01378                 if (paddingLeft) computedBox.padding.left = declaredBox.padding.getLeftWidth(mapper.getCurrentIteration());
01379                 if (paddingRight) computedBox.padding.right = declaredBox.padding.getRightWidth(mapper.getCurrentIteration());
01380                 if (marginLeft) computedBox.margin.left = declaredBox.margin.getLeftWidth(mapper.getCurrentIteration());
01381                 if (marginRight) computedBox.margin.right = declaredBox.margin.getRightWidth(mapper.getCurrentIteration());
01382             }
01383 
01385             inline void setComputedWidthValues()
01386             {
01387                 uint32 iteration = mapper.getCurrentIteration();
01388                 declaredBox.content.setComputedWidth(computedBox.content.width, iteration);
01389                 declaredBox.border.setLeftWidth(computedBox.border.left, iteration);
01390                 declaredBox.border.setRightWidth(computedBox.border.right, iteration);
01391                 declaredBox.padding.setLeftWidth(computedBox.padding.left, iteration);
01392                 declaredBox.padding.setRightWidth(computedBox.padding.right, iteration);
01393                 declaredBox.margin.setLeftWidth(computedBox.margin.left, iteration);
01394                 declaredBox.margin.setRightWidth(computedBox.margin.right, iteration);
01395             }
01396 
01398             inline void transferHeightDeclaredValues(bool content = true, bool marginTop = true, bool marginBottom = true, bool borderTop = true, bool borderBottom = true, bool paddingTop = true, bool paddingBottom = true)
01399             {
01400                 if (content) computedBox.content.height = declaredBox.content.getHeight(mapper.getCurrentIteration());
01401                 if (borderTop) computedBox.border.top = declaredBox.border.getTopWidth(mapper.getCurrentIteration());
01402                 if (borderBottom) computedBox.border.bottom = declaredBox.border.getBottomWidth(mapper.getCurrentIteration());
01403                 if (paddingTop) computedBox.padding.top = declaredBox.padding.getTopWidth(mapper.getCurrentIteration());
01404                 if (paddingBottom) computedBox.padding.bottom = declaredBox.padding.getBottomWidth(mapper.getCurrentIteration());
01405                 if (marginTop) computedBox.margin.top = declaredBox.margin.getTopWidth(mapper.getCurrentIteration());
01406                 if (marginBottom) computedBox.margin.bottom = declaredBox.margin.getBottomWidth(mapper.getCurrentIteration());
01407             }
01408 
01410             inline void setComputedHeightValues()
01411             {
01412                 uint32 iteration = mapper.getCurrentIteration();
01413                 declaredBox.content.setComputedHeight(computedBox.content.height, iteration);
01414                 declaredBox.border.setTopHeight(computedBox.border.top, iteration);
01415                 declaredBox.border.setBottomHeight(computedBox.border.bottom, iteration);
01416                 declaredBox.padding.setTopHeight(computedBox.padding.top, iteration);
01417                 declaredBox.padding.setBottomHeight(computedBox.padding.bottom, iteration);
01418                 declaredBox.margin.setTopHeight(computedBox.margin.top, iteration);
01419                 declaredBox.margin.setBottomHeight(computedBox.margin.bottom, iteration);
01420             }
01421 
01422 
01424             inline void setComputedPosValues(const int32 left, const int32 right)
01425             {
01426                 uint32 iteration = mapper.getCurrentIteration();
01427                 declaredPos.setLeft(left, iteration); declaredPos.setRight(right, iteration);
01428             }
01429 
01431             inline void setComputedValues() { setComputedWidthValues(); setComputedHeightValues(); }
01433             inline void transferDeclaredValues(bool content = true, bool margin1 = true, bool margin2 = true, bool border1 = true, bool border2 = true, bool padding1 = true , bool padding2 = true) { transferWidthDeclaredValues(content, margin1, margin2, border1, border2, padding1, padding2); transferHeightDeclaredValues(content, margin1, margin2, border1, border2, padding1, padding2); }
01434 
01435 
01438             inline void solveBlockLevelWidth(uint32 width)
01439             {
01440 //                uint32 width = mapper.getRenderedWidthOf(this);//computedPos.right - computedPos.left;
01441                 // Need to find what value we know, and what need to be computed 
01442                 bool marginLeft = declaredBox.margin.left && !declaredBox.margin.left->isAuto();
01443                 bool marginRight = declaredBox.margin.right && !declaredBox.margin.right->isAuto();
01444                 bool widthSet = declaredBox.content.width && !declaredBox.content.width->isAuto();
01445 
01446 
01447                 transferWidthDeclaredValues(widthSet, marginLeft, marginRight);
01448                 // Is the block over-constrained ?
01449                 if (marginLeft && marginRight && widthSet)
01450                 {
01451                     // Depending on the direction, we need to adjust a margin so it perfectly fit the box
01452                     int newMarginWidth = (int)width - (int)declaredBox.margin.getWidth(mapper.getCurrentIteration()) - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - (int)declaredBox.padding.getWidth(mapper.getCurrentIteration());
01453                     // The constraint can be matched by changing the width
01454                     leftToRight ? computedBox.margin.right = newMarginWidth : computedBox.margin.left = newMarginWidth;
01455                     // Please note that the margin can be negative after this computation
01456                     setComputedWidthValues();
01457                     return;
01458                 }
01459                 
01460                 // Ok, at least one value is auto, so let's adjust it
01461                 if (!widthSet && replacedElement())
01462                 {
01463                     computedBox.content.width = getReplacedWidth();
01464                 } else if (!widthSet)
01465                 {   
01466                     // If width is auto, any other auto value become zero
01467                     if (!marginLeft) computedBox.margin.left = 0;
01468                     if (!marginRight) computedBox.margin.right = 0;
01469 
01470                     int newWidth = (int)width - computedBox.margin.getWidth() - computedBox.padding.getWidth() - computedBox.border.getWidth();
01471                     if (newWidth >= 0)
01472                     {
01473                         computedBox.content.width = (uint32)newWidth;
01474                     } else
01475                     {   // The width can't be respected, let's first set the width to zero
01476                         computedBox.content.width = 0;
01477                         // Then check if the content work with the remaining margin
01478                         if (leftToRight) 
01479                         {
01480                             newWidth = (int)width - computedBox.padding.getWidth() - computedBox.border.getWidth() - computedBox.margin.left;
01481                             // Please note that the margin can be negative after this computation
01482                             computedBox.margin.right = newWidth;
01483                         } else
01484                         {
01485                             newWidth = (int)width - computedBox.padding.getWidth() - computedBox.border.getWidth() - computedBox.margin.right;
01486                             // Please note that the margin can be negative after this computation
01487                             computedBox.margin.left = newWidth;
01488                         }
01489                     }
01490                     setComputedWidthValues();
01491                     return;
01492                 }
01493 
01494                 // Then check if both margin are auto
01495                 if (!marginLeft && !marginRight)
01496                 {
01497                     int newWidth = (int)width - computedBox.content.width - computedBox.padding.getWidth() - computedBox.border.getWidth();
01498                     if (newWidth >= 0)
01499                     {
01500                         computedBox.margin.left = computedBox.margin.right = newWidth / 2;
01501                         // Make computation is correct even for odd number ;-)
01502                         if (newWidth & 1) computedBox.margin.left ++;
01503                     } else
01504                     {   // Please note that the right margin is negative here
01505                         computedBox.margin.left = 0; computedBox.margin.right = newWidth;
01506                     }
01507                     setComputedWidthValues();
01508                     return;
01509                 }
01510 
01511                 if (!marginLeft)
01512                 {
01513                     int newWidth = (int)width - computedBox.content.width - computedBox.padding.getWidth() - computedBox.border.getWidth() - computedBox.margin.right;
01514                     if (newWidth >= 0)
01515                         computedBox.margin.left = newWidth;
01516                     else 
01517                     {   // Please note that the right margin is negative here
01518                         computedBox.margin.left = 0; computedBox.margin.right = newWidth;
01519                     }
01520                 } else
01521                 {
01522                     int newWidth = (int)width - computedBox.content.width - computedBox.padding.getWidth() - computedBox.border.getWidth() - computedBox.margin.left;
01523                     computedBox.margin.right = newWidth;
01524                 }
01525                 setComputedWidthValues();
01526                 return;
01527             }
01528             
01531             inline void solveAbsoluteBlockLevelWidth(uint32 width)
01532             {
01533 //                uint32 width = mapper.getRenderedWidthOf(this); //computedPos.right - computedPos.left;
01534                 // Need to find what value we know, and what need to be computed 
01535                 bool left = declaredPos.left && !declaredPos.left->isAuto();
01536                 bool right = declaredPos.right && !declaredPos.right->isAuto();
01537                 bool marginLeft = declaredBox.margin.left && !declaredBox.margin.left->isAuto();
01538                 bool marginRight = declaredBox.margin.right && !declaredBox.margin.right->isAuto();
01539                 bool widthSet = declaredBox.content.width && !declaredBox.content.width->isAuto();
01540 
01541                 transferWidthDeclaredValues(widthSet, marginLeft, marginRight);
01542                 int32 leftValue = declaredPos.getLeft(mapper.getCurrentIteration()), rightValue = declaredPos.getRight(mapper.getCurrentIteration()), marginLeftValue = declaredBox.margin.getLeftWidth(mapper.getCurrentIteration()), marginRightValue = declaredBox.margin.getRightWidth(mapper.getCurrentIteration()), widthValue = declaredBox.content.getWidth(mapper.getCurrentIteration());
01543                 uint32 mask = (left ? 1 : 0) | (right ? 2 : 0) | (marginLeft ? 4 : 0) | (marginRight ? 8 : 0) | (widthSet ? 16 : 0);
01544                 if (!widthSet && replacedElement()) 
01545                 {   // For replaced element, let's use the replaced width
01546                     widthValue = getReplacedWidth();
01547                     mask |= 16;
01548                 }
01549 
01550                 while (1)
01551                 {
01552                     switch (mask)
01553                     {
01554                         // We are over-constrained, so apply 10.3.7.7
01555                     case 31:
01556                         if (leftToRight)
01557                             rightValue = (int)width - marginLeftValue - marginRightValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - widthValue - leftValue;
01558                         else
01559                             leftValue = (int)width - marginLeftValue - marginRightValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - widthValue - rightValue;
01560                         break;
01561                     // Now the cases where there is only one value missing
01562                         // Missing width
01563                     case 15:
01564                         widthValue = (int)width - marginLeftValue - marginRightValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - leftValue - rightValue;
01565                         mask = 31;
01566                         break;
01567                         // Missing marginRight
01568                     case 23:
01569                         marginRightValue = (int)width - marginLeftValue - widthValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - leftValue - rightValue;
01570                         mask = 31;
01571                         break;
01572                         // Missing marginLeft    
01573                     case 27:
01574                         marginLeftValue = (int)width - marginRightValue - widthValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - leftValue - rightValue;
01575                         mask = 31;
01576                         break;
01577                         // Missing right
01578                     case 29:
01579                         rightValue = (int)width - marginRightValue - widthValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - leftValue - marginLeftValue;
01580                         mask = 31;
01581                         break;
01582                         // Missing left
01583                     case 30:
01584                         leftValue = (int)width - marginRightValue - widthValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - rightValue - marginLeftValue;
01585                         mask = 31;
01586                         break;
01587                     // Now the case with 2 value missing
01588                         // Missing both marginLeft and marginRight
01589                     case 19:
01590                         {
01591                             int margin = (int)width - widthValue - (int)declaredBox.border.getWidth(mapper.getCurrentIteration()) - declaredBox.padding.getWidth(mapper.getCurrentIteration()) - rightValue - leftValue;
01592                             marginLeftValue = (margin / 2) + (margin % 1);
01593                             marginRightValue = (margin / 2);
01594                             mask = 31;
01595                             break;
01596                         }
01597                         // Missing too much, need to follow the standard
01598                     default:
01599                         break;
01600                     }
01601                     
01602                     if (mask == 31)
01603                     {
01604                         computedPos.left += leftValue;
01605                         computedPos.right -= rightValue;
01606                         computedBox.margin.left = marginLeftValue;
01607                         computedBox.margin.right = marginRightValue;
01608                         computedBox.content.width = widthValue;
01609                         setComputedPosValues(leftValue, rightValue);
01610                         setComputedWidthValues();
01611                         return;
01612                     } else if ((mask & 1) == 0 && leftToRight)
01613                     {
01614                         leftValue = 0;
01615                         mask |= 1;
01616                     } else if ((mask & 2) == 0 && !leftToRight)
01617                     {
01618                         rightValue = 0;
01619                         mask |= 2;
01620                     } else if ((mask & 16) == 0)
01621                     {   // 10.3.7.3
01622                         if ((mask & 1) == 0) { leftValue = 0; mask |= 1; }
01623                         if ((mask & 2) == 0) { rightValue = 0; mask |= 2; }
01624                     } else if ( (!replacedElement() && (mask & 16) == 0) || (mask & 1) == 0 || (mask & 2) == 0)
01625                     {   // 10.3.7.4
01626                         if ((mask & 4) == 0) { marginLeftValue = 0; mask |= 4; }
01627                         if ((mask & 8) == 0) { marginRightValue = 0; mask |= 8; }
01628                     }
01629                 }
01630             }
01631 
01633             inline void zeroIfAuto(Length * len) const
01634             {
01635                 if (len && len->isAuto()) len->setComputedValue(0, mapper.getCurrentIteration()); 
01636             }
01637 
01639             inline void getContentPosition(ComputedPosition & box) const 
01640                 {   box = computedPos; 
01641                     box.top += computedBox.border.top + computedBox.margin.top + computedBox.padding.top; 
01642                     box.left += computedBox.border.left + computedBox.margin.left + computedBox.padding.left; 
01643                     box.right -= computedBox.border.right + computedBox.margin.right + computedBox.padding.right; 
01644                     box.bottom -= computedBox.border.bottom + computedBox.margin.bottom + computedBox.padding.bottom; }
01645 
01647             inline uint32 getContainedBlockWidth() const   { return computedBox.padding.getWidth() + computedBox.content.getWidth(); }
01649             inline uint32 getContainedBlockHeight() const  { return computedBox.padding.getHeight() + computedBox.content.getHeight(); }
01650             
01651 
01653             inline uint32 getBlockWidth() const   { return getContainedBlockWidth() + computedBox.border.getWidth() + computedBox.margin.getTrueWidth(); }
01655             inline uint32 getBlockHeight() const   { return getContainedBlockHeight() + computedBox.border.getHeight() + computedBox.margin.getTrueHeight(); }
01656 
01658             inline bool displayedAsBlock() const { return displayMode == CSS::DisplayMode::Block || displayMode == CSS::DisplayMode::ListItem || displayMode == CSS::DisplayMode::Compact || displayMode == CSS::DisplayMode::RunIn || displayMode == CSS::DisplayMode::Table || displayMode == CSS::DisplayMode::TableCell; }
01660             inline bool displayedAsInline() const { return displayMode == CSS::DisplayMode::Inline || displayMode == CSS::DisplayMode::InlineTable || displayMode == CSS::DisplayMode::Compact || displayMode == CSS::DisplayMode::RunIn; }
01661 
01663             inline bool isFloating() const  { return clearAndFloat.getFloat() != CSS::ClearAndFloat::None ; }
01665             inline bool isCleared() const   { return clearAndFloat.getClear() != CSS::ClearAndFloat::None ; }
01666 
01668             inline bool isSplit() const { return splitLimit.left != splitLimit.right; }
01670             inline int32 getSplitRightPosition() const { return splitLimit.right; }
01672             inline int32 getSplitLeftPosition() const { return splitLimit.left; }
01673 
01675             inline bool replacedElement() const { return contentType > Text && contentType < Table; }
01677             uint32 getReplacedWidth() { return mapper.getRenderedWidthOf(this); }
01679             uint32 getReplacedHeight() { return mapper.getRenderedHeightOf(this); }
01680 
01684             inline const Border::Side & getBorderSide(uint32 whichOne) const { switch (whichOne) { case 0: return declaredBox.border.top; case 1: return declaredBox.border.left; case 2: return declaredBox.border.right; default: return declaredBox.border.bottom; } }
01687             inline bool  hasBackground() const { return false; }
01688 
01690             inline Box * findPreviousBox() const
01691             {
01692                 if (previous) return previous;
01693                 // If inline box contains inline box (like span in span)
01694                 if (ancestor && !ancestor->displayedAsBlock()) return ancestor;
01695                 // Else, no previous 
01696                 return 0;
01697             }
01698 
01700             inline void returnAllLengths(volatile const HTML::Renderer::Allocators::BaseAllocator * alloc)
01701             {
01702                 if (!alloc) return;
01703                 // Content
01704                 alloc->returnLength(declaredBox.content.width);
01705                 alloc->returnLength(declaredBox.content.height);
01706                 // Border
01707                 alloc->returnLength(declaredBox.border.top.length);
01708                 alloc->returnLength(declaredBox.border.left.length);
01709                 alloc->returnLength(declaredBox.border.right.length);
01710                 alloc->returnLength(declaredBox.border.bottom.length);
01711                 // Padding    
01712                 alloc->returnLength(declaredBox.padding.top);
01713                 alloc->returnLength(declaredBox.padding.left);
01714                 alloc->returnLength(declaredBox.padding.right);
01715                 alloc->returnLength(declaredBox.padding.bottom);
01716                 // Margin    
01717                 alloc->returnLength(declaredBox.margin.top);
01718                 alloc->returnLength(declaredBox.margin.left);
01719                 alloc->returnLength(declaredBox.margin.right);
01720                 alloc->returnLength(declaredBox.margin.bottom);
01721 
01722                 // Position
01723                 alloc->returnLength(declaredPos.top);
01724                 alloc->returnLength(declaredPos.left);
01725                 alloc->returnLength(declaredPos.right);
01726                 alloc->returnLength(declaredPos.bottom);
01727 
01728                 // Line height (equal 0 is just to get the previous value which is deleted)
01729                 alloc->returnLength(lineHeight.setNotOwnedLength(0));
01730             }
01731 
01732         public:
01738 //            Box(Mapper & _mapper, Length & _lineHeight) : mapper(_mapper), lineHeight(_lineHeight) {}
01739 
01743             Box(Mapper & _mapper, const BoxHierarchy * boxHierarchy, const CSS::StyleImplement & style, const ContentType ct = Text, const Strings::FastString & text = "") 
01744                 : mapper(_mapper), UID(boxHierarchy), iteration(0), renderAsAnonymousBlock(false), splitLimit(0, 0),
01745                   declaredBox(  style.contentWidth, style.contentHeight,
01746                                 style.paddingTop, style.paddingLeft, style.paddingRight, style.paddingBottom,
01747                                 style.marginTop, style.marginLeft, style.marginRight, style.marginBottom,
01748                                 style.borderTop, style.borderTopStyle, style.borderTopColor,
01749                                 style.borderLeft, style.borderLeftStyle, style.borderLeftColor,
01750                                 style.borderRight, style.borderRightStyle, style.borderRightColor,
01751                                 style.borderBottom, style.borderBottomStyle, style.borderBottomColor),
01752                   declaredPos(style.positionType, style.positionTop, style.positionLeft, style.positionRight, style.positionBottom),                                                  
01753                   displayMode(style.displayMode),
01754                   leftToRight(style.leftToRight),
01755                   lineHeight(style.lineHeight), boxFont(style.font),
01756                   clearAndFloat(style.floating, style.clearing),
01757                   contentType(ct), contentText(text),
01758                   textAlign(style.textAlign), verticalAlign(style.verticalAlign), textDecoration(style.textDecoration),
01759                   ancestor(0), previous(0), next(0), container(0), child(0)
01760             {}
01761                 
01762 
01763             // Allow direct access to the mapper
01764         public:
01765             friend class Mapper;
01766         };
01767     }
01768 }
01769 
01770 
01771 
01772 #endif

(C) An X-Ryl669 project 2007

This document describes Unlimited Zooming Interface source code. UZI stands for Unlimited Zooming Interface, and source code license is