OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/paint/TableCellPainter.h" | |
7 | |
8 #include "core/paint/BlockPainter.h" | |
9 #include "core/paint/BoxPainter.h" | |
10 #include "core/paint/DrawingRecorder.h" | |
11 #include "core/rendering/PaintInfo.h" | |
12 #include "core/rendering/RenderTableCell.h" | |
13 | |
14 namespace blink { | |
15 | |
16 inline CollapsedBorderValue TableCellPainter::cachedCollapsedLeftBorder(const Re nderStyle* styleForCellFlow) const | |
17 { | |
18 if (styleForCellFlow->isHorizontalWritingMode()) | |
19 return styleForCellFlow->isLeftToRightDirection() ? m_renderTableCell.se ction()->cachedCollapsedBorder(&m_renderTableCell, CBSStart) : m_renderTableCell .section()->cachedCollapsedBorder(&m_renderTableCell, CBSEnd); | |
leviw_travelin_and_unemployed
2014/11/13 21:05:52
Maybe wrap this? These are long even for me :p
chrishtr
2014/11/13 21:31:23
Done.
| |
20 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? m_renderTableCel l.section()->cachedCollapsedBorder(&m_renderTableCell, CBSAfter) : m_renderTable Cell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSBefore); | |
21 } | |
22 | |
23 inline CollapsedBorderValue TableCellPainter::cachedCollapsedRightBorder(const R enderStyle* styleForCellFlow) const | |
24 { | |
25 if (styleForCellFlow->isHorizontalWritingMode()) | |
26 return styleForCellFlow->isLeftToRightDirection() ? m_renderTableCell.se ction()->cachedCollapsedBorder(&m_renderTableCell, CBSEnd) : m_renderTableCell.s ection()->cachedCollapsedBorder(&m_renderTableCell, CBSStart); | |
27 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? m_renderTableCel l.section()->cachedCollapsedBorder(&m_renderTableCell, CBSBefore) : m_renderTabl eCell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSAfter); | |
28 } | |
29 | |
30 inline CollapsedBorderValue TableCellPainter::cachedCollapsedTopBorder(const Ren derStyle* styleForCellFlow) const | |
31 { | |
32 if (styleForCellFlow->isHorizontalWritingMode()) | |
33 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? m_renderTabl eCell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSAfter) : m_renderT ableCell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSBefore); | |
34 return styleForCellFlow->isLeftToRightDirection() ? m_renderTableCell.sectio n()->cachedCollapsedBorder(&m_renderTableCell, CBSStart) : m_renderTableCell.sec tion()->cachedCollapsedBorder(&m_renderTableCell, CBSEnd); | |
35 } | |
36 | |
37 inline CollapsedBorderValue TableCellPainter::cachedCollapsedBottomBorder(const RenderStyle* styleForCellFlow) const | |
38 { | |
39 if (styleForCellFlow->isHorizontalWritingMode()) | |
40 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? m_renderTabl eCell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSBefore) : m_render TableCell.section()->cachedCollapsedBorder(&m_renderTableCell, CBSAfter); | |
41 return styleForCellFlow->isLeftToRightDirection() ? m_renderTableCell.sectio n()->cachedCollapsedBorder(&m_renderTableCell, CBSEnd) : m_renderTableCell.secti on()->cachedCollapsedBorder(&m_renderTableCell, CBSStart); | |
42 } | |
43 | |
44 void TableCellPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse t) | |
45 { | |
46 ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders); | |
47 BlockPainter(m_renderTableCell).paint(paintInfo, paintOffset); | |
48 } | |
49 | |
50 struct CollapsedBorder { | |
51 CollapsedBorderValue borderValue; | |
52 BoxSide side; | |
53 bool shouldPaint; | |
54 int x1; | |
55 int y1; | |
56 int x2; | |
57 int y2; | |
58 EBorderStyle style; | |
59 }; | |
60 | |
61 class CollapsedBorders { | |
62 public: | |
63 CollapsedBorders() | |
64 : m_count(0) | |
65 { | |
66 } | |
67 | |
68 void addBorder(const CollapsedBorderValue& borderValue, BoxSide borderSide, bool shouldPaint, int x1, int y1, int x2, int y2, EBorderStyle borderStyle) | |
69 { | |
70 if (borderValue.exists() && shouldPaint) { | |
71 m_borders[m_count].borderValue = borderValue; | |
72 m_borders[m_count].side = borderSide; | |
73 m_borders[m_count].shouldPaint = shouldPaint; | |
74 m_borders[m_count].x1 = x1; | |
75 m_borders[m_count].x2 = x2; | |
76 m_borders[m_count].y1 = y1; | |
77 m_borders[m_count].y2 = y2; | |
78 m_borders[m_count].style = borderStyle; | |
79 m_count++; | |
80 } | |
81 } | |
82 | |
83 CollapsedBorder* nextBorder() | |
84 { | |
85 for (unsigned i = 0; i < m_count; i++) { | |
86 if (m_borders[i].borderValue.exists() && m_borders[i].shouldPaint) { | |
87 m_borders[i].shouldPaint = false; | |
88 return &m_borders[i]; | |
89 } | |
90 } | |
91 | |
92 return 0; | |
93 } | |
94 | |
95 CollapsedBorder m_borders[4]; | |
96 unsigned m_count; | |
97 }; | |
98 | |
99 static EBorderStyle collapsedBorderStyle(EBorderStyle style) | |
100 { | |
101 if (style == OUTSET) | |
102 return GROOVE; | |
103 if (style == INSET) | |
104 return RIDGE; | |
105 return style; | |
106 } | |
107 | |
108 void TableCellPainter::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutP oint& paintOffset) | |
109 { | |
110 ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders); | |
111 | |
112 if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell) || m_renderTableCel l.style()->visibility() != VISIBLE) | |
113 return; | |
114 | |
115 LayoutRect paintRect = LayoutRect(paintOffset + m_renderTableCell.location() , m_renderTableCell.pixelSnappedSize()); | |
116 if (paintRect.y() - m_renderTableCell.table()->outerBorderTop() >= paintInfo .rect.maxY()) | |
117 return; | |
118 | |
119 if (paintRect.maxY() + m_renderTableCell.table()->outerBorderBottom() <= pai ntInfo.rect.y()) | |
120 return; | |
121 | |
122 if (!m_renderTableCell.table()->currentBorderValue()) | |
123 return; | |
124 | |
125 const RenderStyle* styleForCellFlow = m_renderTableCell.styleForCellFlow(); | |
126 CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(styleForCellFlow); | |
127 CollapsedBorderValue rightVal = cachedCollapsedRightBorder(styleForCellFlow) ; | |
128 CollapsedBorderValue topVal = cachedCollapsedTopBorder(styleForCellFlow); | |
129 CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(styleForCellFlo w); | |
130 | |
131 // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location. | |
132 int topWidth = topVal.width(); | |
133 int bottomWidth = bottomVal.width(); | |
134 int leftWidth = leftVal.width(); | |
135 int rightWidth = rightVal.width(); | |
136 | |
137 IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2, | |
138 paintRect.y() - topWidth / 2, | |
139 paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2, | |
140 paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2); | |
141 | |
142 EBorderStyle topStyle = collapsedBorderStyle(topVal.style()); | |
143 EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style()); | |
144 EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style()); | |
145 EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style()); | |
146 | |
147 bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent(); | |
148 bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent(); | |
149 bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent(); | |
150 bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent(); | |
151 | |
152 // We never paint diagonals at the joins. We simply let the border with the highest | |
153 // precedence paint on top of borders with lower precedence. | |
154 CollapsedBorders borders; | |
155 borders.addBorder(topVal, BSTop, renderTop, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, topStyle); | |
156 borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderR ect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle); | |
157 borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y( ), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle); | |
158 borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightW idth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle); | |
159 | |
160 GraphicsContext* graphicsContext = paintInfo.context; | |
161 bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext); | |
162 | |
163 for (CollapsedBorder* border = borders.nextBorder(); border; border = border s.nextBorder()) { | |
164 if (border->borderValue.isSameIgnoringColor(*m_renderTableCell.table()-> currentBorderValue())) { | |
165 ObjectPainter::drawLineForBoxSide(graphicsContext, border->x1, borde r->y1, border->x2, border->y2, border->side, | |
166 border->borderValue.color().resolve(m_renderTableCell.style()->v isitedDependentColor(CSSPropertyColor)), border->style, 0, 0, antialias); | |
167 } | |
168 } | |
169 } | |
170 | |
171 void TableCellPainter::paintBackgroundsBehindCell(PaintInfo& paintInfo, const La youtPoint& paintOffset, RenderObject* backgroundObject) | |
172 { | |
173 if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell)) | |
174 return; | |
175 | |
176 if (!backgroundObject) | |
177 return; | |
178 | |
179 if (m_renderTableCell.style()->visibility() != VISIBLE) | |
180 return; | |
181 | |
182 RenderTable* tableElt = m_renderTableCell.table(); | |
183 if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild()) | |
184 return; | |
185 | |
186 LayoutPoint adjustedPaintOffset = paintOffset; | |
187 if (backgroundObject != &m_renderTableCell) | |
188 adjustedPaintOffset.moveBy(m_renderTableCell.location()); | |
189 | |
190 Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor); | |
191 const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers(); | |
192 | |
193 if (bgLayer.hasImage() || c.alpha()) { | |
194 // We have to clip here because the background would paint | |
195 // on top of the borders otherwise. This only matters for cells and row s. | |
196 bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == & m_renderTableCell || backgroundObject == m_renderTableCell.parent()) && tableElt ->collapseBorders(); | |
197 GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip); | |
198 if (shouldClip) { | |
199 LayoutRect clipRect(adjustedPaintOffset.x() + m_renderTableCell.bord erLeft(), adjustedPaintOffset.y() + m_renderTableCell.borderTop(), | |
200 m_renderTableCell.width() - m_renderTableCell.borderLeft() - m_r enderTableCell.borderRight(), m_renderTableCell.height() - m_renderTableCell.bor derTop() - m_renderTableCell.borderBottom()); | |
201 paintInfo.context->clip(clipRect); | |
202 } | |
203 BoxPainter(m_renderTableCell).paintFillLayers(paintInfo, c, bgLayer, Lay outRect(adjustedPaintOffset, m_renderTableCell.pixelSnappedSize()), BackgroundBl eedNone, CompositeSourceOver, backgroundObject); | |
204 } | |
205 } | |
206 | |
207 void TableCellPainter::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset) | |
208 { | |
209 if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell)) | |
210 return; | |
211 | |
212 RenderTable* tableElt = m_renderTableCell.table(); | |
213 if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild()) | |
214 return; | |
215 | |
216 LayoutRect paintRect = LayoutRect(paintOffset, m_renderTableCell.pixelSnappe dSize()); | |
217 DrawingRecorder recorder(paintInfo.context, &m_renderTableCell, paintInfo.ph ase, pixelSnappedIntRect(paintRect)); | |
218 BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Normal); | |
219 | |
220 // Paint our cell background. | |
221 paintBackgroundsBehindCell(paintInfo, paintOffset, &m_renderTableCell); | |
222 | |
223 BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Inset); | |
224 | |
225 if (!m_renderTableCell.style()->hasBorder() || tableElt->collapseBorders()) | |
226 return; | |
227 | |
228 BoxPainter::paintBorder(m_renderTableCell, paintInfo, paintRect, m_renderTab leCell.style()); | |
229 } | |
230 | |
231 void TableCellPainter::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintO ffset) | |
232 { | |
233 if (m_renderTableCell.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) | |
234 return; | |
235 | |
236 RenderTable* tableElt = m_renderTableCell.table(); | |
237 if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild()) | |
238 return; | |
239 | |
240 BoxPainter(m_renderTableCell).paintMaskImages(paintInfo, LayoutRect(paintOff set, m_renderTableCell.pixelSnappedSize())); | |
241 } | |
242 | |
243 } // namespace blink | |
244 | |
OLD | NEW |