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 Apple Computer, Inc.
      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 "core/rendering/RenderFrameSet.h"
     26 
     27 #include "core/dom/Document.h"
     28 #include "core/dom/EventNames.h"
     29 #include "core/dom/MouseEvent.h"
     30 #include "core/html/HTMLDimension.h"
     31 #include "core/html/HTMLFrameSetElement.h"
     32 #include "core/page/EventHandler.h"
     33 #include "core/page/Frame.h"
     34 #include "core/platform/Cursor.h"
     35 #include "core/platform/graphics/GraphicsContext.h"
     36 #include "core/rendering/PaintInfo.h"
     37 #include "core/rendering/RenderFrame.h"
     38 #include "core/rendering/RenderView.h"
     39 
     40 namespace WebCore {
     41 
     42 RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet)
     43     : RenderBox(frameSet)
     44     , m_isResizing(false)
     45     , m_isChildResizing(false)
     46 {
     47     setInline(false);
     48 }
     49 
     50 RenderFrameSet::~RenderFrameSet()
     51 {
     52 }
     53 
     54 RenderFrameSet::GridAxis::GridAxis()
     55     : m_splitBeingResized(noSplit)
     56 {
     57 }
     58 
     59 inline HTMLFrameSetElement* RenderFrameSet::frameSet() const
     60 {
     61     return static_cast<HTMLFrameSetElement*>(node());
     62 }
     63 
     64 static Color borderStartEdgeColor()
     65 {
     66     return Color(170, 170, 170);
     67 }
     68 
     69 static Color borderEndEdgeColor()
     70 {
     71     return Color::black;
     72 }
     73 
     74 static Color borderFillColor()
     75 {
     76     return Color(208, 208, 208);
     77 }
     78 
     79 void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect)
     80 {
     81     if (!paintInfo.rect.intersects(borderRect))
     82         return;
     83 
     84     // FIXME: We should do something clever when borders from distinct framesets meet at a join.
     85 
     86     // Fill first.
     87     GraphicsContext* context = paintInfo.context;
     88     context->fillRect(borderRect, frameSet()->hasBorderColor() ? resolveColor(CSSPropertyBorderLeftColor) : borderFillColor());
     89 
     90     // Now stroke the edges but only if we have enough room to paint both edges with a little
     91     // bit of the fill color showing through.
     92     if (borderRect.width() >= 3) {
     93         context->fillRect(IntRect(borderRect.location(), IntSize(1, height())), borderStartEdgeColor());
     94         context->fillRect(IntRect(IntPoint(borderRect.maxX() - 1, borderRect.y()), IntSize(1, height())), borderEndEdgeColor());
     95     }
     96 }
     97 
     98 void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& borderRect)
     99 {
    100     if (!paintInfo.rect.intersects(borderRect))
    101         return;
    102 
    103     // FIXME: We should do something clever when borders from distinct framesets meet at a join.
    104 
    105     // Fill first.
    106     GraphicsContext* context = paintInfo.context;
    107     context->fillRect(borderRect, frameSet()->hasBorderColor() ? resolveColor(CSSPropertyBorderLeftColor) : borderFillColor());
    108 
    109     // Now stroke the edges but only if we have enough room to paint both edges with a little
    110     // bit of the fill color showing through.
    111     if (borderRect.height() >= 3) {
    112         context->fillRect(IntRect(borderRect.location(), IntSize(width(), 1)), borderStartEdgeColor());
    113         context->fillRect(IntRect(IntPoint(borderRect.x(), borderRect.maxY() - 1), IntSize(width(), 1)), borderEndEdgeColor());
    114     }
    115 }
    116 
    117 void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    118 {
    119     ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
    120 
    121     if (paintInfo.phase != PaintPhaseForeground)
    122         return;
    123 
    124     RenderObject* child = firstChild();
    125     if (!child)
    126         return;
    127 
    128     LayoutPoint adjustedPaintOffset = paintOffset + location();
    129 
    130     size_t rows = m_rows.m_sizes.size();
    131     size_t cols = m_cols.m_sizes.size();
    132     LayoutUnit borderThickness = frameSet()->border();
    133 
    134     LayoutUnit yPos = 0;
    135     for (size_t r = 0; r < rows; r++) {
    136         LayoutUnit xPos = 0;
    137         for (size_t c = 0; c < cols; c++) {
    138             child->paint(paintInfo, adjustedPaintOffset);
    139             xPos += m_cols.m_sizes[c];
    140             if (borderThickness && m_cols.m_allowBorder[c + 1]) {
    141                 paintColumnBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height())));
    142                 xPos += borderThickness;
    143             }
    144             child = child->nextSibling();
    145             if (!child)
    146                 return;
    147         }
    148         yPos += m_rows.m_sizes[r];
    149         if (borderThickness && m_rows.m_allowBorder[r + 1]) {
    150             paintRowBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness)));
    151             yPos += borderThickness;
    152         }
    153     }
    154 }
    155 
    156 void RenderFrameSet::GridAxis::resize(int size)
    157 {
    158     m_sizes.resize(size);
    159     m_deltas.resize(size);
    160     m_deltas.fill(0);
    161 
    162     // To track edges for resizability and borders, we need to be (size + 1). This is because a parent frameset
    163     // may ask us for information about our left/top/right/bottom edges in order to make its own decisions about
    164     // what to do. We are capable of tainting that parent frameset's borders, so we have to cache this info.
    165     m_preventResize.resize(size + 1);
    166     m_allowBorder.resize(size + 1);
    167 }
    168 
    169 void RenderFrameSet::layOutAxis(GridAxis& axis, const Vector<HTMLDimension>& grid, int availableLen)
    170 {
    171     availableLen = max(availableLen, 0);
    172 
    173     int* gridLayout = axis.m_sizes.data();
    174 
    175     if (grid.isEmpty()) {
    176         gridLayout[0] = availableLen;
    177         return;
    178     }
    179 
    180     int gridLen = axis.m_sizes.size();
    181     ASSERT(gridLen);
    182 
    183     int totalRelative = 0;
    184     int totalFixed = 0;
    185     int totalPercent = 0;
    186     int countRelative = 0;
    187     int countFixed = 0;
    188     int countPercent = 0;
    189 
    190     // First we need to investigate how many columns of each type we have and
    191     // how much space these columns are going to require.
    192     for (int i = 0; i < gridLen; ++i) {
    193         // Count the total length of all of the fixed columns/rows -> totalFixed
    194         // Count the number of columns/rows which are fixed -> countFixed
    195         if (grid[i].isAbsolute()) {
    196             gridLayout[i] = max<int>(grid[i].value(), 0);
    197             totalFixed += gridLayout[i];
    198             countFixed++;
    199         }
    200 
    201         // Count the total percentage of all of the percentage columns/rows -> totalPercent
    202         // Count the number of columns/rows which are percentages -> countPercent
    203         if (grid[i].isPercentage()) {
    204             gridLayout[i] = max<int>(grid[i].value() * availableLen / 100., 0);
    205             totalPercent += gridLayout[i];
    206             countPercent++;
    207         }
    208 
    209         // Count the total relative of all the relative columns/rows -> totalRelative
    210         // Count the number of columns/rows which are relative -> countRelative
    211         if (grid[i].isRelative()) {
    212             totalRelative += max<int>(grid[i].value(), 1);
    213             countRelative++;
    214         }
    215     }
    216 
    217     int remainingLen = availableLen;
    218 
    219     // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed
    220     // columns/rows we need to proportionally adjust their size.
    221     if (totalFixed > remainingLen) {
    222         int remainingFixed = remainingLen;
    223 
    224         for (int i = 0; i < gridLen; ++i) {
    225             if (grid[i].isAbsolute()) {
    226                 gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed;
    227                 remainingLen -= gridLayout[i];
    228             }
    229         }
    230     } else
    231         remainingLen -= totalFixed;
    232 
    233     // Percentage columns/rows are our second priority. Divide the remaining space proportionally
    234     // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative
    235     // to 100%, but to the total percentage. For example, if there are three columns, each of 75%,
    236     // and the available space is 300px, each column will become 100px in width.
    237     if (totalPercent > remainingLen) {
    238         int remainingPercent = remainingLen;
    239 
    240         for (int i = 0; i < gridLen; ++i) {
    241             if (grid[i].isPercentage()) {
    242                 gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent;
    243                 remainingLen -= gridLayout[i];
    244             }
    245         }
    246     } else
    247         remainingLen -= totalPercent;
    248 
    249     // Relative columns/rows are our last priority. Divide the remaining space proportionally
    250     // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*.
    251     if (countRelative) {
    252         int lastRelative = 0;
    253         int remainingRelative = remainingLen;
    254 
    255         for (int i = 0; i < gridLen; ++i) {
    256             if (grid[i].isRelative()) {
    257                 gridLayout[i] = (max(grid[i].value(), 1.) * remainingRelative) / totalRelative;
    258                 remainingLen -= gridLayout[i];
    259                 lastRelative = i;
    260             }
    261         }
    262 
    263         // If we could not evenly distribute the available space of all of the relative
    264         // columns/rows, the remainder will be added to the last column/row.
    265         // For example: if we have a space of 100px and three columns (*,*,*), the remainder will
    266         // be 1px and will be added to the last column: 33px, 33px, 34px.
    267         if (remainingLen) {
    268             gridLayout[lastRelative] += remainingLen;
    269             remainingLen = 0;
    270         }
    271     }
    272 
    273     // If we still have some left over space we need to divide it over the already existing
    274     // columns/rows
    275     if (remainingLen) {
    276         // Our first priority is to spread if over the percentage columns. The remaining
    277         // space is spread evenly, for example: if we have a space of 100px, the columns
    278         // definition of 25%,25% used to result in two columns of 25px. After this the
    279         // columns will each be 50px in width.
    280         if (countPercent && totalPercent) {
    281             int remainingPercent = remainingLen;
    282             int changePercent = 0;
    283 
    284             for (int i = 0; i < gridLen; ++i) {
    285                 if (grid[i].isPercentage()) {
    286                     changePercent = (remainingPercent * gridLayout[i]) / totalPercent;
    287                     gridLayout[i] += changePercent;
    288                     remainingLen -= changePercent;
    289                 }
    290             }
    291         } else if (totalFixed) {
    292             // Our last priority is to spread the remaining space over the fixed columns.
    293             // For example if we have 100px of space and two column of each 40px, both
    294             // columns will become exactly 50px.
    295             int remainingFixed = remainingLen;
    296             int changeFixed = 0;
    297 
    298             for (int i = 0; i < gridLen; ++i) {
    299                 if (grid[i].isAbsolute()) {
    300                     changeFixed = (remainingFixed * gridLayout[i]) / totalFixed;
    301                     gridLayout[i] += changeFixed;
    302                     remainingLen -= changeFixed;
    303                 }
    304             }
    305         }
    306     }
    307 
    308     // If we still have some left over space we probably ended up with a remainder of
    309     // a division. We cannot spread it evenly anymore. If we have any percentage
    310     // columns/rows simply spread the remainder equally over all available percentage columns,
    311     // regardless of their size.
    312     if (remainingLen && countPercent) {
    313         int remainingPercent = remainingLen;
    314         int changePercent = 0;
    315 
    316         for (int i = 0; i < gridLen; ++i) {
    317             if (grid[i].isPercentage()) {
    318                 changePercent = remainingPercent / countPercent;
    319                 gridLayout[i] += changePercent;
    320                 remainingLen -= changePercent;
    321             }
    322         }
    323     } else if (remainingLen && countFixed) {
    324         // If we don't have any percentage columns/rows we only have
    325         // fixed columns. Spread the remainder equally over all fixed
    326         // columns/rows.
    327         int remainingFixed = remainingLen;
    328         int changeFixed = 0;
    329 
    330         for (int i = 0; i < gridLen; ++i) {
    331             if (grid[i].isAbsolute()) {
    332                 changeFixed = remainingFixed / countFixed;
    333                 gridLayout[i] += changeFixed;
    334                 remainingLen -= changeFixed;
    335             }
    336         }
    337     }
    338 
    339     // Still some left over. Add it to the last column, because it is impossible
    340     // spread it evenly or equally.
    341     if (remainingLen)
    342         gridLayout[gridLen - 1] += remainingLen;
    343 
    344     // now we have the final layout, distribute the delta over it
    345     bool worked = true;
    346     int* gridDelta = axis.m_deltas.data();
    347     for (int i = 0; i < gridLen; ++i) {
    348         if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
    349             worked = false;
    350         gridLayout[i] += gridDelta[i];
    351     }
    352     // if the deltas broke something, undo them
    353     if (!worked) {
    354         for (int i = 0; i < gridLen; ++i)
    355             gridLayout[i] -= gridDelta[i];
    356         axis.m_deltas.fill(0);
    357     }
    358 }
    359 
    360 void RenderFrameSet::notifyFrameEdgeInfoChanged()
    361 {
    362     if (needsLayout())
    363         return;
    364     // FIXME: We should only recompute the edge info with respect to the frame that changed
    365     // and its adjacent frame(s) instead of recomputing the edge info for the entire frameset.
    366     computeEdgeInfo();
    367 }
    368 
    369 void RenderFrameSet::fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c)
    370 {
    371     if (edgeInfo.allowBorder(LeftFrameEdge))
    372         m_cols.m_allowBorder[c] = true;
    373     if (edgeInfo.allowBorder(RightFrameEdge))
    374         m_cols.m_allowBorder[c + 1] = true;
    375     if (edgeInfo.preventResize(LeftFrameEdge))
    376         m_cols.m_preventResize[c] = true;
    377     if (edgeInfo.preventResize(RightFrameEdge))
    378         m_cols.m_preventResize[c + 1] = true;
    379 
    380     if (edgeInfo.allowBorder(TopFrameEdge))
    381         m_rows.m_allowBorder[r] = true;
    382     if (edgeInfo.allowBorder(BottomFrameEdge))
    383         m_rows.m_allowBorder[r + 1] = true;
    384     if (edgeInfo.preventResize(TopFrameEdge))
    385         m_rows.m_preventResize[r] = true;
    386     if (edgeInfo.preventResize(BottomFrameEdge))
    387         m_rows.m_preventResize[r + 1] = true;
    388 }
    389 
    390 void RenderFrameSet::computeEdgeInfo()
    391 {
    392     m_rows.m_preventResize.fill(frameSet()->noResize());
    393     m_rows.m_allowBorder.fill(false);
    394     m_cols.m_preventResize.fill(frameSet()->noResize());
    395     m_cols.m_allowBorder.fill(false);
    396 
    397     RenderObject* child = firstChild();
    398     if (!child)
    399         return;
    400 
    401     size_t rows = m_rows.m_sizes.size();
    402     size_t cols = m_cols.m_sizes.size();
    403     for (size_t r = 0; r < rows; ++r) {
    404         for (size_t c = 0; c < cols; ++c) {
    405             FrameEdgeInfo edgeInfo;
    406             if (child->isFrameSet())
    407                 edgeInfo = toRenderFrameSet(child)->edgeInfo();
    408             else
    409                 edgeInfo = toRenderFrame(child)->edgeInfo();
    410             fillFromEdgeInfo(edgeInfo, r, c);
    411             child = child->nextSibling();
    412             if (!child)
    413                 return;
    414         }
    415     }
    416 }
    417 
    418 FrameEdgeInfo RenderFrameSet::edgeInfo() const
    419 {
    420     FrameEdgeInfo result(frameSet()->noResize(), true);
    421 
    422     int rows = frameSet()->totalRows();
    423     int cols = frameSet()->totalCols();
    424     if (rows && cols) {
    425         result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]);
    426         result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]);
    427         result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]);
    428         result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]);
    429         result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]);
    430         result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]);
    431         result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]);
    432         result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]);
    433     }
    434 
    435     return result;
    436 }
    437 
    438 void RenderFrameSet::layout()
    439 {
    440     StackStats::LayoutCheckPoint layoutCheckPoint;
    441     ASSERT(needsLayout());
    442 
    443     bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout();
    444     LayoutRect oldBounds;
    445     RenderLayerModelObject* repaintContainer = 0;
    446     if (doFullRepaint) {
    447         repaintContainer = containerForRepaint();
    448         oldBounds = clippedOverflowRectForRepaint(repaintContainer);
    449     }
    450 
    451     if (!parent()->isFrameSet() && !document()->printing()) {
    452         setWidth(view()->viewWidth());
    453         setHeight(view()->viewHeight());
    454     }
    455 
    456     unsigned cols = frameSet()->totalCols();
    457     unsigned rows = frameSet()->totalRows();
    458 
    459     if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
    460         m_rows.resize(rows);
    461         m_cols.resize(cols);
    462     }
    463 
    464     LayoutUnit borderThickness = frameSet()->border();
    465     layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness);
    466     layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness);
    467 
    468     positionFrames();
    469 
    470     RenderBox::layout();
    471 
    472     computeEdgeInfo();
    473 
    474     updateLayerTransform();
    475 
    476     if (doFullRepaint) {
    477         repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds));
    478         LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer);
    479         if (newBounds != oldBounds)
    480             repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds));
    481     }
    482 
    483     clearNeedsLayout();
    484 }
    485 
    486 void RenderFrameSet::positionFrames()
    487 {
    488     RenderBox* child = firstChildBox();
    489     if (!child)
    490         return;
    491 
    492     int rows = frameSet()->totalRows();
    493     int cols = frameSet()->totalCols();
    494 
    495     int yPos = 0;
    496     int borderThickness = frameSet()->border();
    497     for (int r = 0; r < rows; r++) {
    498         int xPos = 0;
    499         int height = m_rows.m_sizes[r];
    500         for (int c = 0; c < cols; c++) {
    501             child->setLocation(IntPoint(xPos, yPos));
    502             int width = m_cols.m_sizes[c];
    503 
    504             // has to be resized and itself resize its contents
    505             if (width != child->width() || height != child->height()) {
    506                 child->setWidth(width);
    507                 child->setHeight(height);
    508                 child->setNeedsLayout();
    509                 child->layout();
    510             }
    511 
    512             xPos += width + borderThickness;
    513 
    514             child = child->nextSiblingBox();
    515             if (!child)
    516                 return;
    517         }
    518         yPos += height + borderThickness;
    519     }
    520 
    521     // all the remaining frames are hidden to avoid ugly spurious unflowed frames
    522     for (; child; child = child->nextSiblingBox()) {
    523         child->setWidth(0);
    524         child->setHeight(0);
    525         child->clearNeedsLayout();
    526     }
    527 }
    528 
    529 void RenderFrameSet::startResizing(GridAxis& axis, int position)
    530 {
    531     int split = hitTestSplit(axis, position);
    532     if (split == noSplit || axis.m_preventResize[split]) {
    533         axis.m_splitBeingResized = noSplit;
    534         return;
    535     }
    536     axis.m_splitBeingResized = split;
    537     axis.m_splitResizeOffset = position - splitPosition(axis, split);
    538 }
    539 
    540 void RenderFrameSet::continueResizing(GridAxis& axis, int position)
    541 {
    542     if (needsLayout())
    543         return;
    544     if (axis.m_splitBeingResized == noSplit)
    545         return;
    546     int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized);
    547     int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset;
    548     if (!delta)
    549         return;
    550     axis.m_deltas[axis.m_splitBeingResized - 1] += delta;
    551     axis.m_deltas[axis.m_splitBeingResized] -= delta;
    552     setNeedsLayout();
    553 }
    554 
    555 bool RenderFrameSet::userResize(MouseEvent* evt)
    556 {
    557     if (!m_isResizing) {
    558         if (needsLayout())
    559             return false;
    560         if (evt->type() == eventNames().mousedownEvent && evt->button() == LeftButton) {
    561             FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms);
    562             startResizing(m_cols, localPos.x());
    563             startResizing(m_rows, localPos.y());
    564             if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) {
    565                 setIsResizing(true);
    566                 return true;
    567             }
    568         }
    569     } else {
    570         if (evt->type() == eventNames().mousemoveEvent || (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton)) {
    571             FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms);
    572             continueResizing(m_cols, localPos.x());
    573             continueResizing(m_rows, localPos.y());
    574             if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) {
    575                 setIsResizing(false);
    576                 return true;
    577             }
    578         }
    579     }
    580 
    581     return false;
    582 }
    583 
    584 void RenderFrameSet::setIsResizing(bool isResizing)
    585 {
    586     m_isResizing = isResizing;
    587     for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
    588         if (ancestor->isFrameSet())
    589             toRenderFrameSet(ancestor)->m_isChildResizing = isResizing;
    590     }
    591     if (Frame* frame = this->frame())
    592         frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0);
    593 }
    594 
    595 bool RenderFrameSet::isResizingRow() const
    596 {
    597     return m_isResizing && m_rows.m_splitBeingResized != noSplit;
    598 }
    599 
    600 bool RenderFrameSet::isResizingColumn() const
    601 {
    602     return m_isResizing && m_cols.m_splitBeingResized != noSplit;
    603 }
    604 
    605 bool RenderFrameSet::canResizeRow(const IntPoint& p) const
    606 {
    607     int r = hitTestSplit(m_rows, p.y());
    608     return r != noSplit && !m_rows.m_preventResize[r];
    609 }
    610 
    611 bool RenderFrameSet::canResizeColumn(const IntPoint& p) const
    612 {
    613     int c = hitTestSplit(m_cols, p.x());
    614     return c != noSplit && !m_cols.m_preventResize[c];
    615 }
    616 
    617 int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const
    618 {
    619     if (needsLayout())
    620         return 0;
    621 
    622     int borderThickness = frameSet()->border();
    623 
    624     int size = axis.m_sizes.size();
    625     if (!size)
    626         return 0;
    627 
    628     int position = 0;
    629     for (int i = 0; i < split && i < size; ++i)
    630         position += axis.m_sizes[i] + borderThickness;
    631     return position - borderThickness;
    632 }
    633 
    634 int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const
    635 {
    636     if (needsLayout())
    637         return noSplit;
    638 
    639     int borderThickness = frameSet()->border();
    640     if (borderThickness <= 0)
    641         return noSplit;
    642 
    643     size_t size = axis.m_sizes.size();
    644     if (!size)
    645         return noSplit;
    646 
    647     int splitPosition = axis.m_sizes[0];
    648     for (size_t i = 1; i < size; ++i) {
    649         if (position >= splitPosition && position < splitPosition + borderThickness)
    650             return i;
    651         splitPosition += borderThickness + axis.m_sizes[i];
    652     }
    653     return noSplit;
    654 }
    655 
    656 bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const
    657 {
    658     return child->isFrame() || child->isFrameSet();
    659 }
    660 
    661 CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const
    662 {
    663     IntPoint roundedPoint = roundedIntPoint(point);
    664     if (canResizeRow(roundedPoint)) {
    665         cursor = rowResizeCursor();
    666         return SetCursor;
    667     }
    668     if (canResizeColumn(roundedPoint)) {
    669         cursor = columnResizeCursor();
    670         return SetCursor;
    671     }
    672     return RenderBox::getCursor(point, cursor);
    673 }
    674 
    675 } // namespace WebCore
    676