123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- /*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
- #include "config.h"
- #include "RenderFieldset.h"
- #include "CSSPropertyNames.h"
- #include "GraphicsContext.h"
- #include "HTMLNames.h"
- #include "PaintInfo.h"
- using std::min;
- using std::max;
- namespace WebCore {
- using namespace HTMLNames;
- RenderFieldset::RenderFieldset(Element* element)
- : RenderBlock(element)
- {
- }
- void RenderFieldset::computePreferredLogicalWidths()
- {
- RenderBlock::computePreferredLogicalWidths();
- if (RenderBox* legend = findLegend()) {
- int legendMinWidth = legend->minPreferredLogicalWidth();
- Length legendMarginLeft = legend->style()->marginLeft();
- Length legendMarginRight = legend->style()->marginLeft();
- if (legendMarginLeft.isFixed())
- legendMinWidth += legendMarginLeft.value();
- if (legendMarginRight.isFixed())
- legendMinWidth += legendMarginRight.value();
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWidth + borderAndPaddingWidth());
- }
- }
- RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
- {
- RenderBox* legend = findLegend();
- if (legend) {
- if (relayoutChildren)
- legend->setNeedsLayout(true);
- legend->layoutIfNeeded();
- LayoutUnit logicalLeft;
- if (style()->isLeftToRightDirection()) {
- switch (legend->style()->textAlign()) {
- case CENTER:
- logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
- break;
- case RIGHT:
- logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
- break;
- default:
- logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
- break;
- }
- } else {
- switch (legend->style()->textAlign()) {
- case LEFT:
- logicalLeft = borderStart() + paddingStart();
- break;
- case CENTER: {
- // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
- // in LTR).
- LayoutUnit centeredWidth = logicalWidth() - logicalWidthForChild(legend);
- logicalLeft = centeredWidth - centeredWidth / 2;
- break;
- }
- default:
- logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
- break;
- }
- }
- setLogicalLeftForChild(legend, logicalLeft);
- LayoutUnit fieldsetBorderBefore = borderBefore();
- LayoutUnit legendLogicalHeight = logicalHeightForChild(legend);
- LayoutUnit legendLogicalTop;
- LayoutUnit collapsedLegendExtent;
- // FIXME: We need to account for the legend's margin before too.
- if (fieldsetBorderBefore > legendLogicalHeight) {
- // The <legend> is smaller than the associated fieldset before border
- // so the latter determines positioning of the <legend>. The sizing depends
- // on the legend's margins as we want to still follow the author's cues.
- // Firefox completely ignores the margins in this case which seems wrong.
- legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
- collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(legend));
- } else
- collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(legend);
- setLogicalTopForChild(legend, legendLogicalTop);
- setLogicalHeight(paddingBefore() + collapsedLegendExtent);
- }
- return legend;
- }
- RenderBox* RenderFieldset::findLegend(FindLegendOption option) const
- {
- for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
- if (option == IgnoreFloatingOrOutOfFlow && legend->isFloatingOrOutOfFlowPositioned())
- continue;
-
- if (legend->node() && (legend->node()->hasTagName(legendTag)))
- return toRenderBox(legend);
- }
- return 0;
- }
- void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
- {
- if (!paintInfo.shouldPaintWithinRoot(this))
- return;
- LayoutRect paintRect(paintOffset, size());
- RenderBox* legend = findLegend();
- if (!legend)
- return RenderBlock::paintBoxDecorations(paintInfo, paintOffset);
- // FIXME: We need to work with "rl" and "bt" block flow directions. In those
- // cases the legend is embedded in the right and bottom borders respectively.
- // https://bugs.webkit.org/show_bug.cgi?id=47236
- if (style()->isHorizontalWritingMode()) {
- LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
- paintRect.setHeight(paintRect.height() - yOff);
- paintRect.setY(paintRect.y() + yOff);
- } else {
- LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
- paintRect.setWidth(paintRect.width() - xOff);
- paintRect.setX(paintRect.x() + xOff);
- }
- if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
- paintBoxShadow(paintInfo, paintRect, style(), Normal);
- paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect);
- paintBoxShadow(paintInfo, paintRect, style(), Inset);
- if (!style()->hasBorder())
- return;
-
- // Create a clipping region around the legend and paint the border as normal
- GraphicsContext* graphicsContext = paintInfo.context;
- GraphicsContextStateSaver stateSaver(*graphicsContext);
- // FIXME: We need to work with "rl" and "bt" block flow directions. In those
- // cases the legend is embedded in the right and bottom borders respectively.
- // https://bugs.webkit.org/show_bug.cgi?id=47236
- if (style()->isHorizontalWritingMode()) {
- LayoutUnit clipTop = paintRect.y();
- LayoutUnit clipHeight = max(static_cast<LayoutUnit>(style()->borderTopWidth()), legend->height() - ((legend->height() - borderTop()) / 2));
- graphicsContext->clipOut(pixelSnappedIntRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight));
- } else {
- LayoutUnit clipLeft = paintRect.x();
- LayoutUnit clipWidth = max(static_cast<LayoutUnit>(style()->borderLeftWidth()), legend->width());
- graphicsContext->clipOut(pixelSnappedIntRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height()));
- }
- paintBorder(paintInfo, paintRect, style());
- }
- void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
- {
- if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
- return;
- LayoutRect paintRect = LayoutRect(paintOffset, size());
- RenderBox* legend = findLegend();
- if (!legend)
- return RenderBlock::paintMask(paintInfo, paintOffset);
- // FIXME: We need to work with "rl" and "bt" block flow directions. In those
- // cases the legend is embedded in the right and bottom borders respectively.
- // https://bugs.webkit.org/show_bug.cgi?id=47236
- if (style()->isHorizontalWritingMode()) {
- LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
- paintRect.expand(0, -yOff);
- paintRect.move(0, yOff);
- } else {
- LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
- paintRect.expand(-xOff, 0);
- paintRect.move(xOff, 0);
- }
- paintMaskImages(paintInfo, paintRect);
- }
- } // namespace WebCore
|