Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / paint / TableCellPainter.cpp
blobdf6e36cb8f733caa03c6d810ae8b82d8bdb31081
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.
5 #include "config.h"
6 #include "core/paint/TableCellPainter.h"
8 #include "core/layout/LayoutTableCell.h"
9 #include "core/paint/BlockPainter.h"
10 #include "core/paint/BoxPainter.h"
11 #include "core/paint/LayoutObjectDrawingRecorder.h"
12 #include "core/paint/PaintInfo.h"
13 #include "platform/graphics/GraphicsContextStateSaver.h"
15 namespace blink {
17 inline const CollapsedBorderValue& TableCellPainter::cachedCollapsedLeftBorder(const ComputedStyle& styleForCellFlow) const
19 if (styleForCellFlow.isHorizontalWritingMode()) {
20 return styleForCellFlow.isLeftToRightDirection() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSStart)
21 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSEnd);
23 return styleForCellFlow.isFlippedBlocksWritingMode() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSAfter)
24 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSBefore);
27 inline const CollapsedBorderValue& TableCellPainter::cachedCollapsedRightBorder(const ComputedStyle& styleForCellFlow) const
29 if (styleForCellFlow.isHorizontalWritingMode()) {
30 return styleForCellFlow.isLeftToRightDirection() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSEnd)
31 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSStart);
33 return styleForCellFlow.isFlippedBlocksWritingMode() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSBefore)
34 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSAfter);
37 inline const CollapsedBorderValue& TableCellPainter::cachedCollapsedTopBorder(const ComputedStyle& styleForCellFlow) const
39 if (styleForCellFlow.isHorizontalWritingMode())
40 return styleForCellFlow.isFlippedBlocksWritingMode() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSAfter) : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSBefore);
41 return styleForCellFlow.isLeftToRightDirection() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSStart) : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSEnd);
44 inline const CollapsedBorderValue& TableCellPainter::cachedCollapsedBottomBorder(const ComputedStyle& styleForCellFlow) const
46 if (styleForCellFlow.isHorizontalWritingMode()) {
47 return styleForCellFlow.isFlippedBlocksWritingMode() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSBefore)
48 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSAfter);
50 return styleForCellFlow.isLeftToRightDirection() ? m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSEnd)
51 : m_layoutTableCell.section()->cachedCollapsedBorder(&m_layoutTableCell, CBSStart);
54 void TableCellPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
56 ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders);
57 BlockPainter(m_layoutTableCell).paint(paintInfo, paintOffset);
60 static EBorderStyle collapsedBorderStyle(EBorderStyle style)
62 if (style == OUTSET)
63 return GROOVE;
64 if (style == INSET)
65 return RIDGE;
66 return style;
69 void TableCellPainter::paintCollapsedBorders(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
71 ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);
73 if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell) || m_layoutTableCell.style()->visibility() != VISIBLE)
74 return;
76 const CollapsedBorderValue* tableCurrentBorderValue = m_layoutTableCell.table()->currentBorderValue();
77 if (!tableCurrentBorderValue)
78 return;
80 const ComputedStyle& styleForCellFlow = m_layoutTableCell.styleForCellFlow();
81 const CollapsedBorderValue& leftBorderValue = cachedCollapsedLeftBorder(styleForCellFlow);
82 const CollapsedBorderValue& rightBorderValue = cachedCollapsedRightBorder(styleForCellFlow);
83 const CollapsedBorderValue& topBorderValue = cachedCollapsedTopBorder(styleForCellFlow);
84 const CollapsedBorderValue& bottomBorderValue = cachedCollapsedBottomBorder(styleForCellFlow);
86 int displayItemType = DisplayItem::TableCollapsedBorderBase;
87 if (topBorderValue.shouldPaint(*tableCurrentBorderValue))
88 displayItemType |= DisplayItem::TableCollapsedBorderTop;
89 if (bottomBorderValue.shouldPaint(*tableCurrentBorderValue))
90 displayItemType |= DisplayItem::TableCollapsedBorderBottom;
91 if (leftBorderValue.shouldPaint(*tableCurrentBorderValue))
92 displayItemType |= DisplayItem::TableCollapsedBorderLeft;
93 if (rightBorderValue.shouldPaint(*tableCurrentBorderValue))
94 displayItemType |= DisplayItem::TableCollapsedBorderRight;
96 if (displayItemType == DisplayItem::TableCollapsedBorderBase)
97 return;
99 // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
100 int topWidth = topBorderValue.width();
101 int bottomWidth = bottomBorderValue.width();
102 int leftWidth = leftBorderValue.width();
103 int rightWidth = rightBorderValue.width();
105 LayoutRect paintRect = paintBounds(paintOffset, AddOffsetFromParent);
106 IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
107 paintRect.y() - topWidth / 2,
108 paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
109 paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);
111 if (!borderRect.intersects(paintInfo.rect))
112 return;
114 GraphicsContext* graphicsContext = paintInfo.context;
115 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*graphicsContext, m_layoutTableCell, static_cast<DisplayItem::Type>(displayItemType), paintOffset))
116 return;
118 LayoutObjectDrawingRecorder recorder(*graphicsContext, m_layoutTableCell, static_cast<DisplayItem::Type>(displayItemType), borderRect, paintOffset);
119 Color cellColor = m_layoutTableCell.resolveColor(CSSPropertyColor);
121 // We never paint diagonals at the joins. We simply let the border with the highest
122 // precedence paint on top of borders with lower precedence.
123 if (displayItemType & DisplayItem::TableCollapsedBorderTop) {
124 ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, BSTop,
125 topBorderValue.color().resolve(cellColor), collapsedBorderStyle(topBorderValue.style()), 0, 0, true);
127 if (displayItemType & DisplayItem::TableCollapsedBorderBottom) {
128 ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), BSBottom,
129 bottomBorderValue.color().resolve(cellColor), collapsedBorderStyle(bottomBorderValue.style()), 0, 0, true);
131 if (displayItemType & DisplayItem::TableCollapsedBorderLeft) {
132 ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), BSLeft,
133 leftBorderValue.color().resolve(cellColor), collapsedBorderStyle(leftBorderValue.style()), 0, 0, true);
135 if (displayItemType & DisplayItem::TableCollapsedBorderRight) {
136 ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), BSRight,
137 rightBorderValue.color().resolve(cellColor), collapsedBorderStyle(rightBorderValue.style()), 0, 0, true);
141 void TableCellPainter::paintBackgroundsBehindCell(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutObject* backgroundObject)
143 if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell))
144 return;
146 if (!backgroundObject)
147 return;
149 if (m_layoutTableCell.style()->visibility() != VISIBLE)
150 return;
152 LayoutTable* tableElt = m_layoutTableCell.table();
153 if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
154 return;
156 Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor);
157 const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers();
159 LayoutRect paintRect = paintBounds(paintOffset, backgroundObject != &m_layoutTableCell ? AddOffsetFromParent : DoNotAddOffsetFromParent);
161 if (bgLayer.hasImage() || c.alpha()) {
162 // We have to clip here because the background would paint
163 // on top of the borders otherwise. This only matters for cells and rows.
164 bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == &m_layoutTableCell || backgroundObject == m_layoutTableCell.parent()) && tableElt->collapseBorders();
165 GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
166 if (shouldClip) {
167 LayoutRect clipRect(paintRect.location(), m_layoutTableCell.size());
168 clipRect.expand(m_layoutTableCell.borderInsets());
169 paintInfo.context->clip(pixelSnappedIntRect(clipRect));
171 BoxPainter(m_layoutTableCell).paintFillLayers(paintInfo, c, bgLayer, paintRect, BackgroundBleedNone, SkXfermode::kSrcOver_Mode, backgroundObject);
175 void TableCellPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
177 if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell))
178 return;
180 LayoutTable* table = m_layoutTableCell.table();
181 if (!table->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
182 return;
184 bool needsToPaintBorder = m_layoutTableCell.styleRef().hasBorderDecoration() && !table->collapseBorders();
185 if (!m_layoutTableCell.hasBackground() && !m_layoutTableCell.styleRef().boxShadow() && !needsToPaintBorder)
186 return;
188 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutTableCell, DisplayItem::BoxDecorationBackground, paintOffset))
189 return;
191 LayoutRect visualOverflowRect = m_layoutTableCell.visualOverflowRect();
192 visualOverflowRect.moveBy(paintOffset);
193 // TODO(chrishtr): the pixel-snapping here is likely incorrect.
194 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutTableCell, DisplayItem::BoxDecorationBackground, pixelSnappedIntRect(visualOverflowRect), paintOffset);
196 LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
198 BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Normal);
200 // Paint our cell background.
201 paintBackgroundsBehindCell(paintInfo, paintOffset, &m_layoutTableCell);
203 BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Inset);
205 if (!needsToPaintBorder)
206 return;
208 BoxPainter::paintBorder(m_layoutTableCell, paintInfo, paintRect, m_layoutTableCell.styleRef());
211 void TableCellPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
213 if (m_layoutTableCell.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
214 return;
216 LayoutTable* tableElt = m_layoutTableCell.table();
217 if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
218 return;
220 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutTableCell, paintInfo.phase, paintOffset))
221 return;
223 LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
224 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutTableCell, paintInfo.phase, paintRect, paintOffset);
225 BoxPainter(m_layoutTableCell).paintMaskImages(paintInfo, paintRect);
228 LayoutRect TableCellPainter::paintBounds(const LayoutPoint& paintOffset, PaintBoundOffsetBehavior paintBoundOffsetBehavior)
230 LayoutPoint adjustedPaintOffset = paintOffset;
231 if (paintBoundOffsetBehavior == AddOffsetFromParent)
232 adjustedPaintOffset.moveBy(m_layoutTableCell.location());
233 return LayoutRect(adjustedPaintOffset, LayoutSize(m_layoutTableCell.pixelSnappedSize()));
236 } // namespace blink