Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2000 Simon Hausmann <hausmann (at) kde.org>
      4  *           (C) 2000 Stefan Schimanski (1Stein (at) gmx.de)
      5  * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  *
     22  */
     23 
     24 #include "config.h"
     25 #include "RenderPartObject.h"
     26 
     27 #include "Frame.h"
     28 #include "FrameLoaderClient.h"
     29 #include "HTMLEmbedElement.h"
     30 #include "HTMLIFrameElement.h"
     31 #include "HTMLNames.h"
     32 #include "HTMLObjectElement.h"
     33 #include "HTMLParamElement.h"
     34 #include "MIMETypeRegistry.h"
     35 #include "Page.h"
     36 #include "RenderView.h"
     37 #include "RenderWidgetProtector.h"
     38 #include "Text.h"
     39 
     40 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     41 #include "HTMLVideoElement.h"
     42 #endif
     43 
     44 namespace WebCore {
     45 
     46 using namespace HTMLNames;
     47 
     48 RenderPartObject::RenderPartObject(Element* element)
     49     : RenderPart(element)
     50 {
     51 }
     52 
     53 void RenderPartObject::layout()
     54 {
     55     ASSERT(needsLayout());
     56 
     57 #ifdef FLATTEN_IFRAME
     58     RenderPart::calcWidth();
     59     RenderPart::calcHeight();
     60     // Calculate the styled dimensions by subtracting the border and padding.
     61     int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
     62     int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
     63     int styleWidth = width() - extraWidth;
     64     int styleHeight = height() - extraHeight;
     65     // Some IFrames have a width and/or height of 1 when they are meant to be
     66     // hidden. If that is the case, do not try to expand.
     67     if (node()->hasTagName(iframeTag) && widget() && widget()->isFrameView() &&
     68             styleWidth > 1 && styleHeight > 1) {
     69         HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node());
     70         bool scrolling = element->scrollingMode() != ScrollbarAlwaysOff;
     71         bool widthIsFixed = style()->width().isFixed();
     72         bool heightIsFixed = style()->height().isFixed();
     73         // If an iframe has a fixed dimension and suppresses scrollbars, it
     74         // will disrupt layout if we force it to expand. Plus on a desktop,
     75         // the extra content is not accessible.
     76         if (scrolling || !widthIsFixed || !heightIsFixed) {
     77             FrameView* view = static_cast<FrameView*>(widget());
     78             RenderView* root = view ? view->frame()->contentRenderer() : NULL;
     79             if (root && style()->visibility() != HIDDEN) {
     80                 // Update the dimensions to get the correct minimum preferred
     81                 // width
     82                 updateWidgetPosition();
     83 
     84                 // Use the preferred width if it is larger and only if
     85                 // scrollbars are visible or the width style is not fixed.
     86                 if (scrolling || !widthIsFixed)
     87                     setWidth(max(width(), root->minPrefWidth()) + extraWidth);
     88 
     89                 // Resize the view to recalc the height.
     90                 int h = height() - extraHeight;
     91                 int w = width() - extraWidth;
     92                 if (w > view->width())
     93                     h = 0;
     94                 if (w != view->width() || h != view->height()) {
     95                     view->resize(w, h);
     96                 }
     97 
     98                 // Layout the view.
     99                 do {
    100                     view->layout();
    101                 } while (view->layoutPending() || root->needsLayout());
    102 
    103                 int contentHeight = view->contentsHeight();
    104                 int contentWidth = view->contentsWidth();
    105                 // Only change the width or height if scrollbars are visible or
    106                 // if the style is not a fixed value. Use the maximum value so
    107                 // that iframes never shrink.
    108                 if (scrolling || !heightIsFixed)
    109                     setHeight(max(height(), contentHeight + extraHeight));
    110                 if (scrolling || !widthIsFixed)
    111                     setWidth(max(width(), contentWidth + extraWidth));
    112 
    113                 // Update one last time
    114                 updateWidgetPosition();
    115 
    116                 // Layout one more time to ensure all objects have the correct
    117                 // height.
    118                 view->layout();
    119 
    120 #if !ASSERT_DISABLED
    121                 ASSERT(!view->layoutPending());
    122                 ASSERT(!root->needsLayout());
    123                 // Sanity check when assertions are enabled.
    124                 RenderObject* c = root->nextInPreOrder();
    125                 while (c) {
    126                     ASSERT(!c->needsLayout());
    127                     c = c->nextInPreOrder();
    128                 }
    129 #endif
    130             }
    131         }
    132     }
    133 #else
    134     calcWidth();
    135     calcHeight();
    136 #endif
    137 
    138     RenderPart::layout();
    139 
    140     m_overflow.clear();
    141     addShadowOverflow();
    142 
    143     setNeedsLayout(false);
    144 }
    145 
    146 #ifdef FLATTEN_IFRAME
    147 void RenderPartObject::calcWidth() {
    148     RenderPart::calcWidth();
    149     if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView())
    150         return;
    151     FrameView* view = static_cast<FrameView*>(widget());
    152     RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer());
    153     if (!root)
    154         return;
    155     // Do not expand if the scrollbars are suppressed and the width is fixed.
    156     bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff;
    157     if (!scrolling && style()->width().isFixed())
    158         return;
    159     // Update the dimensions to get the correct minimum preferred
    160     // width
    161     updateWidgetPosition();
    162 
    163     int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
    164     // Set the width
    165     setWidth(max(width(), root->minPrefWidth()) + extraWidth);
    166 
    167     // Update based on the new width
    168     updateWidgetPosition();
    169 
    170     // Layout to get the content width
    171     do {
    172         view->layout();
    173     } while (view->layoutPending() || root->needsLayout());
    174 
    175     setWidth(max(width(), view->contentsWidth() + extraWidth));
    176 
    177     // Update one last time to ensure the dimensions.
    178     updateWidgetPosition();
    179 }
    180 
    181 void RenderPartObject::calcHeight() {
    182     RenderPart::calcHeight();
    183     if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView())
    184         return;
    185     FrameView* view = static_cast<FrameView*>(widget());
    186     RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer());
    187     if (!root)
    188         return;
    189     // Do not expand if the scrollbars are suppressed and the height is fixed.
    190     bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff;
    191     if (!scrolling && style()->height().isFixed())
    192         return;
    193     // Update the widget
    194     updateWidgetPosition();
    195 
    196     // Layout to get the content height
    197     do {
    198         view->layout();
    199     } while (view->layoutPending() || root->needsLayout());
    200 
    201     int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
    202     setHeight(max(width(), view->contentsHeight() + extraHeight));
    203 
    204     // Update one last time to ensure the dimensions.
    205     updateWidgetPosition();
    206 }
    207 #endif
    208 
    209 void RenderPartObject::viewCleared()
    210 {
    211     if (node() && widget() && widget()->isFrameView()) {
    212         FrameView* view = static_cast<FrameView*>(widget());
    213         int marginw = -1;
    214         int marginh = -1;
    215         if (node()->hasTagName(iframeTag)) {
    216             HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node());
    217             marginw = frame->getMarginWidth();
    218             marginh = frame->getMarginHeight();
    219         }
    220         if (marginw != -1)
    221             view->setMarginWidth(marginw);
    222         if (marginh != -1)
    223             view->setMarginHeight(marginh);
    224     }
    225 }
    226 
    227 }
    228