Chromium Code Reviews| 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 |