• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
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 "RenderFieldset.h"
26 
27 #include "CSSPropertyNames.h"
28 #include "GraphicsContext.h"
29 #include "HTMLNames.h"
30 #include "PaintInfo.h"
31 
32 #if ENABLE(WML)
33 #include "WMLNames.h"
34 #endif
35 
36 using std::min;
37 using std::max;
38 
39 namespace WebCore {
40 
41 using namespace HTMLNames;
42 
RenderFieldset(Node * element)43 RenderFieldset::RenderFieldset(Node* element)
44     : RenderBlock(element)
45 {
46 }
47 
computePreferredLogicalWidths()48 void RenderFieldset::computePreferredLogicalWidths()
49 {
50     RenderBlock::computePreferredLogicalWidths();
51     if (RenderBox* legend = findLegend()) {
52         int legendMinWidth = legend->minPreferredLogicalWidth();
53 
54         Length legendMarginLeft = legend->style()->marginLeft();
55         Length legendMarginRight = legend->style()->marginLeft();
56 
57         if (legendMarginLeft.isFixed())
58             legendMinWidth += legendMarginLeft.value();
59 
60         if (legendMarginRight.isFixed())
61             legendMinWidth += legendMarginRight.value();
62 
63         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWidth + borderAndPaddingWidth());
64     }
65 }
66 
layoutSpecialExcludedChild(bool relayoutChildren)67 RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
68 {
69     RenderBox* legend = findLegend();
70     if (legend) {
71         if (relayoutChildren)
72             legend->setNeedsLayout(true);
73         legend->layoutIfNeeded();
74 
75         int logicalLeft;
76         if (style()->isLeftToRightDirection()) {
77             switch (legend->style()->textAlign()) {
78             case CENTER:
79                 logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
80                 break;
81             case RIGHT:
82                 logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
83                 break;
84             default:
85                 logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
86                 break;
87             }
88         } else {
89             switch (legend->style()->textAlign()) {
90             case LEFT:
91                 logicalLeft = borderStart() + paddingStart();
92                 break;
93             case CENTER: {
94                 // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
95                 // in LTR).
96                 int centeredWidth = logicalWidth() - logicalWidthForChild(legend);
97                 logicalLeft = centeredWidth - centeredWidth / 2;
98                 break;
99             }
100             default:
101                 logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
102                 break;
103             }
104         }
105 
106         setLogicalLeftForChild(legend, logicalLeft);
107 
108         int b = borderBefore();
109         int h = logicalHeightForChild(legend);
110         setLogicalTopForChild(legend, max((b - h) / 2, 0));
111         setLogicalHeight(max(b, h) + paddingBefore());
112     }
113     return legend;
114 }
115 
findLegend() const116 RenderBox* RenderFieldset::findLegend() const
117 {
118     for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
119         if (!legend->isFloatingOrPositioned() && legend->node() &&
120             (legend->node()->hasTagName(legendTag)
121 #if ENABLE(WML)
122             || legend->node()->hasTagName(WMLNames::insertedLegendTag)
123 #endif
124             )
125            )
126             return toRenderBox(legend);
127     }
128     return 0;
129 }
130 
paintBoxDecorations(PaintInfo & paintInfo,int tx,int ty)131 void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
132 {
133     if (!paintInfo.shouldPaintWithinRoot(this))
134         return;
135 
136     int w = width();
137     int h = height();
138     RenderBox* legend = findLegend();
139     if (!legend)
140         return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);
141 
142     // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
143     // cases the legend is embedded in the right and bottom borders respectively.
144     // https://bugs.webkit.org/show_bug.cgi?id=47236
145     if (style()->isHorizontalWritingMode()) {
146         int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
147         h -= yOff;
148         ty += yOff;
149     } else {
150         int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
151         w -= xOff;
152         tx += xOff;
153     }
154 
155     paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
156 
157     paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h);
158     paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
159 
160     if (!style()->hasBorder())
161         return;
162 
163     // Create a clipping region around the legend and paint the border as normal
164     GraphicsContext* graphicsContext = paintInfo.context;
165     graphicsContext->save();
166 
167     // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
168     // cases the legend is embedded in the right and bottom borders respectively.
169     // https://bugs.webkit.org/show_bug.cgi?id=47236
170     if (style()->isHorizontalWritingMode()) {
171         int clipTop = ty;
172         int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());
173         graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop, legend->width(), clipHeight));
174     } else {
175         int clipLeft = tx;
176         int clipWidth = max(static_cast<int>(style()->borderLeftWidth()), legend->width());
177         graphicsContext->clipOut(IntRect(clipLeft, ty + legend->y(), clipWidth, legend->height()));
178     }
179 
180     paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);
181 
182     graphicsContext->restore();
183 }
184 
paintMask(PaintInfo & paintInfo,int tx,int ty)185 void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
186 {
187     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
188         return;
189 
190     int w = width();
191     int h = height();
192     RenderBox* legend = findLegend();
193     if (!legend)
194         return RenderBlock::paintMask(paintInfo, tx, ty);
195 
196     // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
197     // cases the legend is embedded in the right and bottom borders respectively.
198     // https://bugs.webkit.org/show_bug.cgi?id=47236
199     if (style()->isHorizontalWritingMode()) {
200         int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
201         h -= yOff;
202         ty += yOff;
203     } else {
204         int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
205         w -= xOff;
206         tx += xOff;
207     }
208 
209     paintMaskImages(paintInfo, tx, ty, w, h);
210 }
211 
212 } // namespace WebCore
213