OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
reserved. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 10 matching lines...) Expand all Loading... |
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
22 * Boston, MA 02110-1301, USA. | 22 * Boston, MA 02110-1301, USA. |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #include "core/rendering/RenderTableCell.h" | 26 #include "core/rendering/RenderTableCell.h" |
27 | 27 |
28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
29 #include "core/css/StylePropertySet.h" | 29 #include "core/css/StylePropertySet.h" |
30 #include "core/html/HTMLTableCellElement.h" | 30 #include "core/html/HTMLTableCellElement.h" |
31 #include "core/paint/BoxPainter.h" | 31 #include "core/paint/TableCellPainter.h" |
32 #include "core/paint/DrawingRecorder.h" | |
33 #include "core/rendering/PaintInfo.h" | 32 #include "core/rendering/PaintInfo.h" |
34 #include "core/rendering/RenderTableCol.h" | 33 #include "core/rendering/RenderTableCol.h" |
35 #include "core/rendering/RenderView.h" | 34 #include "core/rendering/RenderView.h" |
36 #include "core/rendering/SubtreeLayoutScope.h" | 35 #include "core/rendering/SubtreeLayoutScope.h" |
37 #include "core/rendering/style/CollapsedBorderValue.h" | 36 #include "core/rendering/style/CollapsedBorderValue.h" |
38 #include "platform/geometry/FloatQuad.h" | 37 #include "platform/geometry/FloatQuad.h" |
39 #include "platform/geometry/TransformState.h" | 38 #include "platform/geometry/TransformState.h" |
40 #include "platform/graphics/GraphicsContextStateSaver.h" | 39 #include "platform/graphics/GraphicsContextStateSaver.h" |
41 | 40 |
42 namespace blink { | 41 namespace blink { |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 | 846 |
848 // (9) The table's after border. | 847 // (9) The table's after border. |
849 result = chooseBorder(result, CollapsedBorderValue(table->style()->borde
rAfter(), includeColor ? table->resolveColor(afterColorProperty) : Color(), BTAB
LE)); | 848 result = chooseBorder(result, CollapsedBorderValue(table->style()->borde
rAfter(), includeColor ? table->resolveColor(afterColorProperty) : Color(), BTAB
LE)); |
850 if (!result.exists()) | 849 if (!result.exists()) |
851 return result; | 850 return result; |
852 } | 851 } |
853 | 852 |
854 return result; | 853 return result; |
855 } | 854 } |
856 | 855 |
857 inline CollapsedBorderValue RenderTableCell::cachedCollapsedLeftBorder(const Ren
derStyle* styleForCellFlow) const | |
858 { | |
859 if (styleForCellFlow->isHorizontalWritingMode()) | |
860 return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCol
lapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd); | |
861 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? section()->cache
dCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBef
ore); | |
862 } | |
863 | |
864 inline CollapsedBorderValue RenderTableCell::cachedCollapsedRightBorder(const Re
nderStyle* styleForCellFlow) const | |
865 { | |
866 if (styleForCellFlow->isHorizontalWritingMode()) | |
867 return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCol
lapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart); | |
868 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? section()->cache
dCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAf
ter); | |
869 } | |
870 | |
871 inline CollapsedBorderValue RenderTableCell::cachedCollapsedTopBorder(const Rend
erStyle* styleForCellFlow) const | |
872 { | |
873 if (styleForCellFlow->isHorizontalWritingMode()) | |
874 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? section()->c
achedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CB
SBefore); | |
875 return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollaps
edBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd); | |
876 } | |
877 | |
878 inline CollapsedBorderValue RenderTableCell::cachedCollapsedBottomBorder(const R
enderStyle* styleForCellFlow) const | |
879 { | |
880 if (styleForCellFlow->isHorizontalWritingMode()) | |
881 return styleForCellFlow->slowIsFlippedBlocksWritingMode() ? section()->c
achedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, C
BSAfter); | |
882 return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollaps
edBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart); | |
883 } | |
884 | |
885 int RenderTableCell::borderLeft() const | 856 int RenderTableCell::borderLeft() const |
886 { | 857 { |
887 return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlockFlow:
:borderLeft(); | 858 return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlockFlow:
:borderLeft(); |
888 } | 859 } |
889 | 860 |
890 int RenderTableCell::borderRight() const | 861 int RenderTableCell::borderRight() const |
891 { | 862 { |
892 return table()->collapseBorders() ? borderHalfRight(false) : RenderBlockFlow
::borderRight(); | 863 return table()->collapseBorders() ? borderHalfRight(false) : RenderBlockFlow
::borderRight(); |
893 } | 864 } |
894 | 865 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 int RenderTableCell::borderHalfAfter(bool outer) const | 954 int RenderTableCell::borderHalfAfter(bool outer) const |
984 { | 955 { |
985 CollapsedBorderValue border = collapsedAfterBorder(DoNotIncludeBorderColor); | 956 CollapsedBorderValue border = collapsedAfterBorder(DoNotIncludeBorderColor); |
986 if (border.exists()) | 957 if (border.exists()) |
987 return (border.width() + ((styleForCellFlow()->slowIsFlippedBlocksWritin
gMode() ^ outer) ? 1 : 0)) / 2; | 958 return (border.width() + ((styleForCellFlow()->slowIsFlippedBlocksWritin
gMode() ^ outer) ? 1 : 0)) / 2; |
988 return 0; | 959 return 0; |
989 } | 960 } |
990 | 961 |
991 void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset
) | 962 void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset
) |
992 { | 963 { |
993 ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders); | 964 TableCellPainter(*this).paint(paintInfo, paintOffset); |
994 RenderBlock::paint(paintInfo, paintOffset); | |
995 } | 965 } |
996 | 966 |
997 static EBorderStyle collapsedBorderStyle(EBorderStyle style) | |
998 { | |
999 if (style == OUTSET) | |
1000 return GROOVE; | |
1001 if (style == INSET) | |
1002 return RIDGE; | |
1003 return style; | |
1004 } | |
1005 | |
1006 struct CollapsedBorder { | |
1007 CollapsedBorderValue borderValue; | |
1008 BoxSide side; | |
1009 bool shouldPaint; | |
1010 int x1; | |
1011 int y1; | |
1012 int x2; | |
1013 int y2; | |
1014 EBorderStyle style; | |
1015 }; | |
1016 | |
1017 class CollapsedBorders { | |
1018 public: | |
1019 CollapsedBorders() | |
1020 : m_count(0) | |
1021 { | |
1022 } | |
1023 | |
1024 void addBorder(const CollapsedBorderValue& borderValue, BoxSide borderSide,
bool shouldPaint, | |
1025 int x1, int y1, int x2, int y2, EBorderStyle borderStyle) | |
1026 { | |
1027 if (borderValue.exists() && shouldPaint) { | |
1028 m_borders[m_count].borderValue = borderValue; | |
1029 m_borders[m_count].side = borderSide; | |
1030 m_borders[m_count].shouldPaint = shouldPaint; | |
1031 m_borders[m_count].x1 = x1; | |
1032 m_borders[m_count].x2 = x2; | |
1033 m_borders[m_count].y1 = y1; | |
1034 m_borders[m_count].y2 = y2; | |
1035 m_borders[m_count].style = borderStyle; | |
1036 m_count++; | |
1037 } | |
1038 } | |
1039 | |
1040 CollapsedBorder* nextBorder() | |
1041 { | |
1042 for (unsigned i = 0; i < m_count; i++) { | |
1043 if (m_borders[i].borderValue.exists() && m_borders[i].shouldPaint) { | |
1044 m_borders[i].shouldPaint = false; | |
1045 return &m_borders[i]; | |
1046 } | |
1047 } | |
1048 | |
1049 return 0; | |
1050 } | |
1051 | |
1052 CollapsedBorder m_borders[4]; | |
1053 unsigned m_count; | |
1054 }; | |
1055 | |
1056 static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues, | 967 static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues, |
1057 CollapsedBorderValue borderValue) | 968 CollapsedBorderValue borderValue) |
1058 { | 969 { |
1059 if (!borderValue.exists()) | 970 if (!borderValue.exists()) |
1060 return; | 971 return; |
1061 size_t count = borderValues.size(); | 972 size_t count = borderValues.size(); |
1062 for (size_t i = 0; i < count; ++i) | 973 for (size_t i = 0; i < count; ++i) |
1063 if (borderValues[i].isSameIgnoringColor(borderValue)) | 974 if (borderValues[i].isSameIgnoringColor(borderValue)) |
1064 return; | 975 return; |
1065 borderValues.append(borderValue); | 976 borderValues.append(borderValue); |
(...skipping 15 matching lines...) Expand all Loading... |
1081 return 0; | 992 return 0; |
1082 return compareBorders(*a, *b); | 993 return compareBorders(*a, *b); |
1083 } | 994 } |
1084 | 995 |
1085 void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borde
rValues) | 996 void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borde
rValues) |
1086 { | 997 { |
1087 qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue)
, | 998 qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue)
, |
1088 compareBorderValuesForQSort); | 999 compareBorderValuesForQSort); |
1089 } | 1000 } |
1090 | 1001 |
1091 void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPo
int& paintOffset) | |
1092 { | |
1093 ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders); | |
1094 | |
1095 if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIB
LE) | |
1096 return; | |
1097 | |
1098 LayoutRect paintRect = LayoutRect(paintOffset + location(), pixelSnappedSize
()); | |
1099 if (paintRect.y() - table()->outerBorderTop() >= paintInfo.rect.maxY()) | |
1100 return; | |
1101 | |
1102 if (paintRect.maxY() + table()->outerBorderBottom() <= paintInfo.rect.y()) | |
1103 return; | |
1104 | |
1105 if (!table()->currentBorderValue()) | |
1106 return; | |
1107 | |
1108 const RenderStyle* styleForCellFlow = this->styleForCellFlow(); | |
1109 CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(styleForCellFlow); | |
1110 CollapsedBorderValue rightVal = cachedCollapsedRightBorder(styleForCellFlow)
; | |
1111 CollapsedBorderValue topVal = cachedCollapsedTopBorder(styleForCellFlow); | |
1112 CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(styleForCellFlo
w); | |
1113 | |
1114 // Adjust our x/y/width/height so that we paint the collapsed borders at the
correct location. | |
1115 int topWidth = topVal.width(); | |
1116 int bottomWidth = bottomVal.width(); | |
1117 int leftWidth = leftVal.width(); | |
1118 int rightWidth = rightVal.width(); | |
1119 | |
1120 IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2, | |
1121 paintRect.y() - topWidth / 2, | |
1122 paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2, | |
1123 paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2); | |
1124 | |
1125 EBorderStyle topStyle = collapsedBorderStyle(topVal.style()); | |
1126 EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style()); | |
1127 EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style()); | |
1128 EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style()); | |
1129 | |
1130 bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent(); | |
1131 bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent(); | |
1132 bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent(); | |
1133 bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent(); | |
1134 | |
1135 // We never paint diagonals at the joins. We simply let the border with the
highest | |
1136 // precedence paint on top of borders with lower precedence. | |
1137 CollapsedBorders borders; | |
1138 borders.addBorder(topVal, BSTop, renderTop, borderRect.x(), borderRect.y(),
borderRect.maxX(), borderRect.y() + topWidth, topStyle); | |
1139 borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderR
ect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle); | |
1140 borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y(
), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle); | |
1141 borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightW
idth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle); | |
1142 | |
1143 GraphicsContext* graphicsContext = paintInfo.context; | |
1144 bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext); | |
1145 | |
1146 for (CollapsedBorder* border = borders.nextBorder(); border; border = border
s.nextBorder()) { | |
1147 if (border->borderValue.isSameIgnoringColor(*table()->currentBorderValue
())) { | |
1148 ObjectPainter::drawLineForBoxSide(graphicsContext, border->x1, borde
r->y1, border->x2, border->y2, border->side, | |
1149 border->borderValue.color().resolve(style()->visitedDependentCol
or(CSSPropertyColor)), border->style, 0, 0, antialias); | |
1150 } | |
1151 } | |
1152 } | |
1153 | |
1154 void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, const Lay
outPoint& paintOffset, RenderObject* backgroundObject) | |
1155 { | |
1156 if (!paintInfo.shouldPaintWithinRoot(this)) | |
1157 return; | |
1158 | |
1159 if (!backgroundObject) | |
1160 return; | |
1161 | |
1162 if (style()->visibility() != VISIBLE) | |
1163 return; | |
1164 | |
1165 RenderTable* tableElt = table(); | |
1166 if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstC
hild()) | |
1167 return; | |
1168 | |
1169 LayoutPoint adjustedPaintOffset = paintOffset; | |
1170 if (backgroundObject != this) | |
1171 adjustedPaintOffset.moveBy(location()); | |
1172 | |
1173 Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor); | |
1174 const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers(); | |
1175 | |
1176 if (bgLayer.hasImage() || c.alpha()) { | |
1177 // We have to clip here because the background would paint | |
1178 // on top of the borders otherwise. This only matters for cells and row
s. | |
1179 bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == t
his || backgroundObject == parent()) && tableElt->collapseBorders(); | |
1180 GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip); | |
1181 if (shouldClip) { | |
1182 LayoutRect clipRect(adjustedPaintOffset.x() + borderLeft(), adjusted
PaintOffset.y() + borderTop(), | |
1183 width() - borderLeft() - borderRight(), height() - borderTop() -
borderBottom()); | |
1184 paintInfo.context->clip(clipRect); | |
1185 } | |
1186 BoxPainter(*this).paintFillLayers(paintInfo, c, bgLayer, LayoutRect(adju
stedPaintOffset, pixelSnappedSize()), BackgroundBleedNone, CompositeSourceOver,
backgroundObject); | |
1187 } | |
1188 } | |
1189 | |
1190 void RenderTableCell::paintBoxDecorationBackground(PaintInfo& paintInfo, const L
ayoutPoint& paintOffset) | 1002 void RenderTableCell::paintBoxDecorationBackground(PaintInfo& paintInfo, const L
ayoutPoint& paintOffset) |
1191 { | 1003 { |
1192 if (!paintInfo.shouldPaintWithinRoot(this)) | 1004 TableCellPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset)
; |
1193 return; | |
1194 | |
1195 RenderTable* tableElt = table(); | |
1196 if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstC
hild()) | |
1197 return; | |
1198 | |
1199 LayoutRect paintRect = LayoutRect(paintOffset, pixelSnappedSize()); | |
1200 DrawingRecorder recorder(paintInfo.context, this, paintInfo.phase, pixelSnap
pedIntRect(paintRect)); | |
1201 BoxPainter::paintBoxShadow(paintInfo, paintRect, style(), Normal); | |
1202 | |
1203 // Paint our cell background. | |
1204 paintBackgroundsBehindCell(paintInfo, paintOffset, this); | |
1205 | |
1206 BoxPainter::paintBoxShadow(paintInfo, paintRect, style(), Inset); | |
1207 | |
1208 if (!style()->hasBorder() || tableElt->collapseBorders()) | |
1209 return; | |
1210 | |
1211 BoxPainter::paintBorder(*this, paintInfo, paintRect, style()); | |
1212 } | 1005 } |
1213 | 1006 |
1214 void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) | 1007 void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) |
1215 { | 1008 { |
1216 if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) | 1009 TableCellPainter(*this).paintMask(paintInfo, paintOffset); |
1217 return; | |
1218 | |
1219 RenderTable* tableElt = table(); | |
1220 if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstC
hild()) | |
1221 return; | |
1222 | |
1223 BoxPainter(*this).paintMaskImages(paintInfo, LayoutRect(paintOffset, pixelSn
appedSize())); | |
1224 } | 1010 } |
1225 | 1011 |
1226 bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoida
nce, InlineFlowBox*) const | 1012 bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoida
nce, InlineFlowBox*) const |
1227 { | 1013 { |
1228 return false; | 1014 return false; |
1229 } | 1015 } |
1230 | 1016 |
1231 void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool ve
rticalScrollbarChanged) | 1017 void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool ve
rticalScrollbarChanged) |
1232 { | 1018 { |
1233 LayoutUnit scrollbarHeight = scrollbarLogicalHeight(); | 1019 LayoutUnit scrollbarHeight = scrollbarLogicalHeight(); |
(...skipping 27 matching lines...) Expand all Loading... |
1261 | 1047 |
1262 RenderTableCell* RenderTableCell::createAnonymousWithParentRenderer(const Render
Object* parent) | 1048 RenderTableCell* RenderTableCell::createAnonymousWithParentRenderer(const Render
Object* parent) |
1263 { | 1049 { |
1264 RenderTableCell* newCell = RenderTableCell::createAnonymous(&parent->documen
t()); | 1050 RenderTableCell* newCell = RenderTableCell::createAnonymous(&parent->documen
t()); |
1265 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), TABLE_CELL); | 1051 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), TABLE_CELL); |
1266 newCell->setStyle(newStyle.release()); | 1052 newCell->setStyle(newStyle.release()); |
1267 return newCell; | 1053 return newCell; |
1268 } | 1054 } |
1269 | 1055 |
1270 } // namespace blink | 1056 } // namespace blink |
OLD | NEW |