Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv ed. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv ed. |
| 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
| 6 * Copyright (C) 2010 Daniel Bates (dbates@intudata.com) | 6 * Copyright (C) 2010 Daniel Bates (dbates@intudata.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 #include "core/layout/LayoutAnalyzer.h" | 29 #include "core/layout/LayoutAnalyzer.h" |
| 30 #include "core/layout/LayoutListItem.h" | 30 #include "core/layout/LayoutListItem.h" |
| 31 #include "core/layout/TextRunConstructor.h" | 31 #include "core/layout/TextRunConstructor.h" |
| 32 #include "core/paint/ListMarkerPainter.h" | 32 #include "core/paint/ListMarkerPainter.h" |
| 33 #include "core/paint/PaintLayer.h" | 33 #include "core/paint/PaintLayer.h" |
| 34 #include "platform/fonts/Font.h" | 34 #include "platform/fonts/Font.h" |
| 35 #include "wtf/text/StringBuilder.h" | 35 #include "wtf/text/StringBuilder.h" |
| 36 | 36 |
| 37 namespace blink { | 37 namespace blink { |
| 38 | 38 |
| 39 // TODO(wkorman): A seemingly arbitrary number tacked on following any image | |
| 40 // and included as part of margin for any text. Look into history, other | |
| 41 // browser behavior, and update or remove as appropriate. | |
| 39 const int cMarkerPadding = 7; | 42 const int cMarkerPadding = 7; |
|
eae
2015/10/12 06:02:01
cMarkerPaddingPx (assuming it is in pixels).
wkorman
2015/10/14 01:55:30
Done.
| |
| 40 | 43 |
| 41 enum SequenceType { NumericSequence, AlphabeticSequence }; | 44 enum SequenceType { NumericSequence, AlphabeticSequence }; |
| 42 | 45 |
| 43 static String toRoman(int number, bool upper) | 46 static String toRoman(int number, bool upper) |
| 44 { | 47 { |
| 45 // FIXME: CSS3 describes how to make this work for much larger numbers, | 48 // FIXME: CSS3 describes how to make this work for much larger numbers, |
| 46 // using overbars and special characters. It also specifies the characters | 49 // using overbars and special characters. It also specifies the characters |
| 47 // in the range U+2160 to U+217F instead of standard ASCII ones. | 50 // in the range U+2160 to U+217F instead of standard ASCII ones. |
| 48 ASSERT(number >= 1 && number <= 3999); | 51 ASSERT(number >= 1 && number <= 3999); |
| 49 | 52 |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 { | 1030 { |
| 1028 return m_image && !m_image->errorOccurred(); | 1031 return m_image && !m_image->errorOccurred(); |
| 1029 } | 1032 } |
| 1030 | 1033 |
| 1031 LayoutRect LayoutListMarker::localSelectionRect() const | 1034 LayoutRect LayoutListMarker::localSelectionRect() const |
| 1032 { | 1035 { |
| 1033 InlineBox* box = inlineBoxWrapper(); | 1036 InlineBox* box = inlineBoxWrapper(); |
| 1034 if (!box) | 1037 if (!box) |
| 1035 return LayoutRect(LayoutPoint(), size()); | 1038 return LayoutRect(LayoutPoint(), size()); |
| 1036 RootInlineBox& root = inlineBoxWrapper()->root(); | 1039 RootInlineBox& root = inlineBoxWrapper()->root(); |
| 1037 LayoutUnit newLogicalTop = root.block().style()->isFlippedBlocksWritingMode( ) ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() : root.selectio nTop() - inlineBoxWrapper()->logicalTop(); | 1040 const ComputedStyle* blockStyle = root.block().style(); |
| 1038 if (root.block().style()->isHorizontalWritingMode()) | 1041 LayoutUnit newLogicalTop = blockStyle->isFlippedBlocksWritingMode() |
| 1042 ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() | |
| 1043 : root.selectionTop() - inlineBoxWrapper()->logicalTop(); | |
| 1044 if (blockStyle->isHorizontalWritingMode()) | |
| 1039 return LayoutRect(0, newLogicalTop, size().width(), root.selectionHeight ()); | 1045 return LayoutRect(0, newLogicalTop, size().width(), root.selectionHeight ()); |
| 1040 return LayoutRect(newLogicalTop, 0, root.selectionHeight(), size().height()) ; | 1046 return LayoutRect(newLogicalTop, 0, root.selectionHeight(), size().height()) ; |
| 1041 } | 1047 } |
| 1042 | 1048 |
| 1043 void LayoutListMarker::paint(const PaintInfo& paintInfo, const LayoutPoint& pain tOffset) const | 1049 void LayoutListMarker::paint(const PaintInfo& paintInfo, const LayoutPoint& pain tOffset) const |
| 1044 { | 1050 { |
| 1045 ListMarkerPainter(*this).paint(paintInfo, paintOffset); | 1051 ListMarkerPainter(*this).paint(paintInfo, paintOffset); |
| 1046 } | 1052 } |
| 1047 | 1053 |
| 1048 void LayoutListMarker::layout() | 1054 void LayoutListMarker::layout() |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 else | 1089 else |
| 1084 setShouldDoFullPaintInvalidation(); | 1090 setShouldDoFullPaintInvalidation(); |
| 1085 } | 1091 } |
| 1086 | 1092 |
| 1087 void LayoutListMarker::updateMarginsAndContent() | 1093 void LayoutListMarker::updateMarginsAndContent() |
| 1088 { | 1094 { |
| 1089 updateContent(); | 1095 updateContent(); |
| 1090 updateMargins(); | 1096 updateMargins(); |
| 1091 } | 1097 } |
| 1092 | 1098 |
| 1093 void LayoutListMarker::updateContent() | 1099 LayoutListMarker::SimplifiedListStyle LayoutListMarker::simplifiedListStyle() co nst |
| 1094 { | 1100 { |
| 1095 // FIXME: This if-statement is just a performance optimization, but it's mes sy to use the preferredLogicalWidths dirty bit for this. | 1101 switch (style()->listStyleType()) { |
| 1096 // It's unclear if this is a premature optimization. | |
| 1097 if (!preferredLogicalWidthsDirty()) | |
| 1098 return; | |
| 1099 | |
| 1100 m_text = ""; | |
| 1101 | |
| 1102 if (isImage()) { | |
| 1103 // FIXME: This is a somewhat arbitrary width. Generated images for mark ers really won't become particularly useful | |
| 1104 // until we support the CSS3 marker pseudoclass to allow control over th e width and height of the marker box. | |
| 1105 int bulletWidth = style()->fontMetrics().ascent() / 2; | |
| 1106 IntSize defaultBulletSize(bulletWidth, bulletWidth); | |
| 1107 IntSize imageSize = calculateImageIntrinsicDimensions(m_image.get(), def aultBulletSize, DoNotScaleByEffectiveZoom); | |
| 1108 m_image->setContainerSizeForLayoutObject(this, imageSize, style()->effec tiveZoom()); | |
| 1109 return; | |
| 1110 } | |
| 1111 | |
| 1112 EListStyleType type = style()->listStyleType(); | |
| 1113 switch (type) { | |
| 1114 case NoneListStyle: | 1102 case NoneListStyle: |
| 1115 break; | 1103 return NoneSimpleStyle; |
| 1104 case Disc: | |
| 1116 case Circle: | 1105 case Circle: |
| 1117 case Disc: | |
| 1118 case Square: | 1106 case Square: |
| 1119 m_text = listMarkerText(type, 0); // value is ignored for these types | 1107 return SymbolSimpleStyle; |
| 1120 break; | |
| 1121 case ArabicIndic: | 1108 case ArabicIndic: |
| 1122 case Armenian: | 1109 case Armenian: |
| 1123 case Bengali: | 1110 case Bengali: |
| 1124 case Cambodian: | 1111 case Cambodian: |
| 1125 case CJKIdeographic: | 1112 case CJKIdeographic: |
| 1126 case CjkEarthlyBranch: | 1113 case CjkEarthlyBranch: |
| 1127 case CjkHeavenlyStem: | 1114 case CjkHeavenlyStem: |
| 1128 case DecimalLeadingZero: | 1115 case DecimalLeadingZero: |
| 1129 case DecimalListStyle: | 1116 case DecimalListStyle: |
| 1130 case Devanagari: | 1117 case Devanagari: |
| 1131 case EthiopicHalehame: | 1118 case EthiopicHalehame: |
| 1132 case EthiopicHalehameAm: | 1119 case EthiopicHalehameAm: |
| 1133 case EthiopicHalehameTiEr: | 1120 case EthiopicHalehameTiEr: |
| 1134 case EthiopicHalehameTiEt: | 1121 case EthiopicHalehameTiEt: |
| 1135 case Georgian: | 1122 case Georgian: |
| 1136 case Gujarati: | 1123 case Gujarati: |
| 1137 case Gurmukhi: | 1124 case Gurmukhi: |
| 1125 case Hebrew: | |
| 1138 case Hangul: | 1126 case Hangul: |
| 1139 case HangulConsonant: | 1127 case HangulConsonant: |
| 1140 case KoreanHangulFormal: | 1128 case KoreanHangulFormal: |
| 1141 case KoreanHanjaFormal: | 1129 case KoreanHanjaFormal: |
| 1142 case KoreanHanjaInformal: | 1130 case KoreanHanjaInformal: |
| 1143 case Hebrew: | |
| 1144 case Hiragana: | 1131 case Hiragana: |
| 1145 case HiraganaIroha: | 1132 case HiraganaIroha: |
| 1146 case Kannada: | 1133 case Kannada: |
| 1147 case Katakana: | 1134 case Katakana: |
| 1148 case KatakanaIroha: | 1135 case KatakanaIroha: |
| 1149 case Khmer: | 1136 case Khmer: |
| 1150 case Lao: | 1137 case Lao: |
| 1151 case LowerAlpha: | 1138 case LowerAlpha: |
| 1152 case LowerArmenian: | 1139 case LowerArmenian: |
| 1153 case LowerGreek: | 1140 case LowerGreek: |
| 1154 case LowerLatin: | 1141 case LowerLatin: |
| 1155 case LowerRoman: | 1142 case LowerRoman: |
| 1156 case Malayalam: | 1143 case Malayalam: |
| 1157 case Mongolian: | 1144 case Mongolian: |
| 1158 case Myanmar: | 1145 case Myanmar: |
| 1159 case Oriya: | 1146 case Oriya: |
| 1160 case Persian: | 1147 case Persian: |
| 1161 case SimpChineseFormal: | 1148 case SimpChineseFormal: |
| 1162 case SimpChineseInformal: | 1149 case SimpChineseInformal: |
| 1163 case Telugu: | 1150 case Telugu: |
| 1164 case Thai: | 1151 case Thai: |
| 1165 case Tibetan: | 1152 case Tibetan: |
| 1166 case TradChineseFormal: | 1153 case TradChineseFormal: |
| 1167 case TradChineseInformal: | 1154 case TradChineseInformal: |
| 1168 case UpperAlpha: | 1155 case UpperAlpha: |
| 1169 case UpperArmenian: | 1156 case UpperArmenian: |
| 1170 case UpperLatin: | 1157 case UpperLatin: |
| 1171 case UpperRoman: | 1158 case UpperRoman: |
| 1172 case Urdu: | 1159 case Urdu: |
| 1173 m_text = listMarkerText(type, m_listItem->value()); | 1160 return LanguageSimpleStyle; |
| 1161 default: | |
| 1162 return NoneSimpleStyle; | |
| 1163 } | |
| 1164 } | |
| 1165 | |
| 1166 void LayoutListMarker::updateContent() | |
| 1167 { | |
| 1168 // FIXME: This if-statement is just a performance optimization, but it's mes sy to use the preferredLogicalWidths dirty bit for this. | |
| 1169 // It's unclear if this is a premature optimization. | |
| 1170 if (!preferredLogicalWidthsDirty()) | |
| 1171 return; | |
| 1172 | |
| 1173 m_text = ""; | |
| 1174 | |
| 1175 if (isImage()) { | |
| 1176 // FIXME: This is a somewhat arbitrary width. Generated images for mark ers really won't become particularly useful | |
| 1177 // until we support the CSS3 marker pseudoclass to allow control over th e width and height of the marker box. | |
| 1178 int bulletWidth = style()->fontMetrics().ascent() / 2; | |
|
eae
2015/10/12 06:02:01
Is flooring the result the tight thing to do here?
wkorman
2015/10/14 01:55:30
Likely to revise this in subsequent changes when I
| |
| 1179 IntSize defaultBulletSize(bulletWidth, bulletWidth); | |
| 1180 IntSize imageSize = calculateImageIntrinsicDimensions(m_image.get(), def aultBulletSize, DoNotScaleByEffectiveZoom); | |
| 1181 m_image->setContainerSizeForLayoutObject(this, imageSize, style()->effec tiveZoom()); | |
| 1182 return; | |
| 1183 } | |
| 1184 | |
| 1185 switch (simplifiedListStyle()) { | |
| 1186 case NoneSimpleStyle: | |
| 1187 break; | |
| 1188 case SymbolSimpleStyle: | |
| 1189 m_text = listMarkerText(style()->listStyleType(), 0); // value is ignore d for these types | |
| 1190 break; | |
| 1191 case LanguageSimpleStyle: | |
| 1192 m_text = listMarkerText(style()->listStyleType(), m_listItem->value()); | |
| 1174 break; | 1193 break; |
| 1175 } | 1194 } |
| 1176 } | 1195 } |
| 1177 | 1196 |
| 1197 LayoutUnit LayoutListMarker::getWidthOfTextWithSuffix(UChar* suffix, int suffixL ength) const | |
| 1198 { | |
| 1199 if (m_text.isEmpty()) | |
| 1200 return 0; | |
| 1201 | |
| 1202 const Font& font = style()->font(); | |
| 1203 LayoutUnit itemWidth = font.width(m_text); | |
| 1204 TextRun run = constructTextRun(font, suffix, suffixLength, styleRef(), style ()->direction()); | |
|
eae
2015/10/12 06:02:01
How about constructing a text run with both the te
wkorman
2015/10/14 01:55:30
Added TODO to look at this, I agree there's redund
| |
| 1205 LayoutUnit suffixSpaceWidth = font.width(run); | |
| 1206 return itemWidth + suffixSpaceWidth; | |
| 1207 } | |
| 1208 | |
| 1178 void LayoutListMarker::computePreferredLogicalWidths() | 1209 void LayoutListMarker::computePreferredLogicalWidths() |
| 1179 { | 1210 { |
| 1180 ASSERT(preferredLogicalWidthsDirty()); | 1211 ASSERT(preferredLogicalWidthsDirty()); |
| 1181 updateContent(); | 1212 updateContent(); |
| 1182 | 1213 |
| 1183 if (isImage()) { | 1214 if (isImage()) { |
| 1184 LayoutSize imageSize = m_image->imageSize(this, style()->effectiveZoom() ); | 1215 LayoutSize imageSize = m_image->imageSize(this, style()->effectiveZoom() ); |
| 1185 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHor izontalWritingMode() ? imageSize.width() : imageSize.height(); | 1216 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHor izontalWritingMode() ? imageSize.width() : imageSize.height(); |
| 1186 clearPreferredLogicalWidthsDirty(); | 1217 clearPreferredLogicalWidthsDirty(); |
| 1187 updateMargins(); | 1218 updateMargins(); |
| 1188 return; | 1219 return; |
| 1189 } | 1220 } |
| 1190 | 1221 |
| 1191 const Font& font = style()->font(); | |
| 1192 | |
| 1193 LayoutUnit logicalWidth = 0; | 1222 LayoutUnit logicalWidth = 0; |
| 1194 EListStyleType type = style()->listStyleType(); | 1223 switch (simplifiedListStyle()) { |
| 1195 switch (type) { | 1224 case NoneSimpleStyle: |
| 1196 case NoneListStyle: | |
| 1197 break; | 1225 break; |
| 1198 case Circle: | 1226 case SymbolSimpleStyle: { |
| 1199 case Disc: | 1227 // For these styles, the text of the marker will be the single character itself, |
| 1200 case Square: | 1228 // and so the only suffix will be a single space character to provide su fficient |
| 1201 logicalWidth = (font.fontMetrics().ascent() * 2 / 3 + 1) / 2 + 2; | 1229 // separation between the list marker text and the associated list item text. |
| 1230 UChar suffix[1] = { listMarkerSuffix(style()->listStyleType(), m_listIte m->value()) }; | |
| 1231 logicalWidth = getWidthOfTextWithSuffix(suffix, 1); | |
| 1232 } | |
| 1202 break; | 1233 break; |
| 1203 case ArabicIndic: | 1234 case LanguageSimpleStyle: { |
| 1204 case Armenian: | 1235 // For these styles, we have some kind of a language-specific separating |
| 1205 case Bengali: | 1236 // character, followed by a space character to provide sufficient |
| 1206 case Cambodian: | 1237 // separation between the list marker text and the associated list item text. |
| 1207 case CJKIdeographic: | 1238 UChar suffixSpace[2] = { listMarkerSuffix(style()->listStyleType(), m_li stItem->value()), ' ' }; |
| 1208 case CjkEarthlyBranch: | 1239 logicalWidth = getWidthOfTextWithSuffix(suffixSpace, 2); |
| 1209 case CjkHeavenlyStem: | |
| 1210 case DecimalLeadingZero: | |
| 1211 case DecimalListStyle: | |
| 1212 case Devanagari: | |
| 1213 case EthiopicHalehame: | |
| 1214 case EthiopicHalehameAm: | |
| 1215 case EthiopicHalehameTiEr: | |
| 1216 case EthiopicHalehameTiEt: | |
| 1217 case Georgian: | |
| 1218 case Gujarati: | |
| 1219 case Gurmukhi: | |
| 1220 case Hangul: | |
| 1221 case HangulConsonant: | |
| 1222 case KoreanHangulFormal: | |
| 1223 case KoreanHanjaFormal: | |
| 1224 case KoreanHanjaInformal: | |
| 1225 case Hebrew: | |
| 1226 case Hiragana: | |
| 1227 case HiraganaIroha: | |
| 1228 case Kannada: | |
| 1229 case Katakana: | |
| 1230 case KatakanaIroha: | |
| 1231 case Khmer: | |
| 1232 case Lao: | |
| 1233 case LowerAlpha: | |
| 1234 case LowerArmenian: | |
| 1235 case LowerGreek: | |
| 1236 case LowerLatin: | |
| 1237 case LowerRoman: | |
| 1238 case Malayalam: | |
| 1239 case Mongolian: | |
| 1240 case Myanmar: | |
| 1241 case Oriya: | |
| 1242 case Persian: | |
| 1243 case SimpChineseFormal: | |
| 1244 case SimpChineseInformal: | |
| 1245 case Telugu: | |
| 1246 case Thai: | |
| 1247 case Tibetan: | |
| 1248 case TradChineseFormal: | |
| 1249 case TradChineseInformal: | |
| 1250 case UpperAlpha: | |
| 1251 case UpperArmenian: | |
| 1252 case UpperLatin: | |
| 1253 case UpperRoman: | |
| 1254 case Urdu: | |
| 1255 if (m_text.isEmpty()) { | |
| 1256 logicalWidth = 0; | |
| 1257 } else { | |
| 1258 LayoutUnit itemWidth = font.width(m_text); | |
| 1259 UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()) , ' ' }; | |
| 1260 LayoutUnit suffixSpaceWidth = font.width(constructTextRun(font, suff ixSpace, 2, styleRef(), style()->direction())); | |
| 1261 logicalWidth = itemWidth + suffixSpaceWidth; | |
| 1262 } | 1240 } |
| 1263 break; | 1241 break; |
| 1264 } | 1242 } |
| 1265 | 1243 |
| 1266 m_minPreferredLogicalWidth = logicalWidth; | 1244 m_minPreferredLogicalWidth = logicalWidth; |
| 1267 m_maxPreferredLogicalWidth = logicalWidth; | 1245 m_maxPreferredLogicalWidth = logicalWidth; |
| 1268 | 1246 |
| 1269 clearPreferredLogicalWidthsDirty(); | 1247 clearPreferredLogicalWidthsDirty(); |
| 1270 | 1248 |
| 1271 updateMargins(); | 1249 updateMargins(); |
| 1272 } | 1250 } |
| 1273 | 1251 |
| 1274 void LayoutListMarker::updateMargins() | 1252 void LayoutListMarker::updateMargins() |
| 1275 { | 1253 { |
| 1276 const FontMetrics& fontMetrics = style()->fontMetrics(); | |
| 1277 | |
| 1278 LayoutUnit marginStart = 0; | 1254 LayoutUnit marginStart = 0; |
| 1279 LayoutUnit marginEnd = 0; | 1255 LayoutUnit marginEnd = 0; |
| 1280 | 1256 |
| 1281 if (isInside()) { | 1257 if (isInside()) { |
| 1282 if (isImage()) { | 1258 if (isImage()) { |
| 1283 marginEnd = cMarkerPadding; | 1259 marginEnd = cMarkerPadding; |
| 1284 } else { | 1260 } else if (simplifiedListStyle() == SymbolSimpleStyle) { |
| 1285 switch (style()->listStyleType()) { | 1261 marginStart = minPreferredLogicalWidth(); |
| 1286 case Disc: | 1262 marginEnd = 0; |
| 1287 case Circle: | |
| 1288 case Square: | |
| 1289 marginStart = -1; | |
| 1290 marginEnd = fontMetrics.ascent() - minPreferredLogicalWidth() + 1; | |
| 1291 break; | |
| 1292 default: | |
| 1293 break; | |
| 1294 } | |
| 1295 } | 1263 } |
| 1296 } else { | 1264 } else { |
| 1297 if (style()->isLeftToRightDirection()) { | 1265 if (style()->isLeftToRightDirection()) { |
| 1298 if (isImage()) { | 1266 if (isImage()) |
| 1299 marginStart = -minPreferredLogicalWidth() - cMarkerPadding; | 1267 marginStart = -minPreferredLogicalWidth() - cMarkerPadding; |
| 1300 } else { | 1268 else if (style()->listStyleType() != NoneListStyle) |
| 1301 int offset = fontMetrics.ascent() * 2 / 3; | 1269 marginStart = m_text.isEmpty() ? LayoutUnit() : -minPreferredLog icalWidth(); |
| 1302 switch (style()->listStyleType()) { | |
| 1303 case Disc: | |
| 1304 case Circle: | |
| 1305 case Square: | |
| 1306 marginStart = -offset - cMarkerPadding - 1; | |
| 1307 break; | |
| 1308 case NoneListStyle: | |
| 1309 break; | |
| 1310 default: | |
| 1311 marginStart = m_text.isEmpty() ? LayoutUnit() : -minPreferre dLogicalWidth() - offset / 2; | |
| 1312 } | |
| 1313 } | |
| 1314 marginEnd = -marginStart - minPreferredLogicalWidth(); | 1270 marginEnd = -marginStart - minPreferredLogicalWidth(); |
| 1315 } else { | 1271 } else { |
| 1316 if (isImage()) { | 1272 if (isImage()) |
| 1317 marginEnd = cMarkerPadding; | 1273 marginEnd = cMarkerPadding; |
| 1318 } else { | 1274 else if (style()->listStyleType() != NoneListStyle) |
| 1319 int offset = fontMetrics.ascent() * 2 / 3; | 1275 marginEnd = 0; |
| 1320 switch (style()->listStyleType()) { | |
| 1321 case Disc: | |
| 1322 case Circle: | |
| 1323 case Square: | |
| 1324 marginEnd = offset + cMarkerPadding + 1 - minPreferredLogica lWidth(); | |
| 1325 break; | |
| 1326 case NoneListStyle: | |
| 1327 break; | |
| 1328 default: | |
| 1329 marginEnd = m_text.isEmpty() ? 0 : offset / 2; | |
| 1330 } | |
| 1331 } | |
| 1332 marginStart = -marginEnd - minPreferredLogicalWidth(); | 1276 marginStart = -marginEnd - minPreferredLogicalWidth(); |
| 1333 } | 1277 } |
| 1334 | |
| 1335 } | 1278 } |
| 1336 | 1279 |
| 1337 mutableStyleRef().setMarginStart(Length(marginStart, Fixed)); | 1280 mutableStyleRef().setMarginStart(Length(marginStart, Fixed)); |
| 1338 mutableStyleRef().setMarginEnd(Length(marginEnd, Fixed)); | 1281 mutableStyleRef().setMarginEnd(Length(marginEnd, Fixed)); |
| 1339 } | 1282 } |
| 1340 | 1283 |
| 1341 LayoutUnit LayoutListMarker::lineHeight(bool firstLine, LineDirectionMode direct ion, LinePositionMode linePositionMode) const | 1284 LayoutUnit LayoutListMarker::lineHeight(bool firstLine, LineDirectionMode direct ion, LinePositionMode linePositionMode) const |
| 1342 { | 1285 { |
| 1343 if (!isImage()) | 1286 if (!isImage()) |
| 1344 return m_listItem->lineHeight(firstLine, direction, PositionOfInteriorLi neBoxes); | 1287 return m_listItem->lineHeight(firstLine, direction, PositionOfInteriorLi neBoxes); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1357 { | 1300 { |
| 1358 return m_listItem->notInList() || style()->listStylePosition() == INSIDE; | 1301 return m_listItem->notInList() || style()->listStylePosition() == INSIDE; |
| 1359 } | 1302 } |
| 1360 | 1303 |
| 1361 IntRect LayoutListMarker::getRelativeMarkerRect() const | 1304 IntRect LayoutListMarker::getRelativeMarkerRect() const |
| 1362 { | 1305 { |
| 1363 if (isImage()) | 1306 if (isImage()) |
| 1364 return IntRect(0, 0, m_image->imageSize(this, style()->effectiveZoom()). width(), m_image->imageSize(this, style()->effectiveZoom()).height()); | 1307 return IntRect(0, 0, m_image->imageSize(this, style()->effectiveZoom()). width(), m_image->imageSize(this, style()->effectiveZoom()).height()); |
| 1365 | 1308 |
| 1366 IntRect relativeRect; | 1309 IntRect relativeRect; |
| 1367 EListStyleType type = style()->listStyleType(); | 1310 switch (simplifiedListStyle()) { |
| 1368 switch (type) { | 1311 case NoneSimpleStyle: |
| 1369 case Disc: | 1312 return IntRect(); |
| 1370 case Circle: | 1313 case SymbolSimpleStyle: { |
| 1371 case Square: { | 1314 // For these styles, the text of the marker will be the single character itself, |
| 1372 // FIXME: Are these particular rounding rules necessary? | 1315 // and so the only suffix will be a single space character to provide su fficient |
| 1373 const FontMetrics& fontMetrics = style()->fontMetrics(); | 1316 // separation between the list marker text and the associated list item text. |
| 1374 int ascent = fontMetrics.ascent(); | 1317 UChar suffix[1] = { listMarkerSuffix(style()->listStyleType(), m_listIte m->value()) }; |
| 1375 int bulletWidth = (ascent * 2 / 3 + 1) / 2; | 1318 LayoutUnit itemWidth = getWidthOfTextWithSuffix(suffix, 1); |
| 1376 relativeRect = IntRect(1, 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth , bulletWidth); | 1319 relativeRect = IntRect(0, 0, itemWidth, style()->font().fontMetrics().he ight()); |
| 1320 } | |
| 1377 break; | 1321 break; |
| 1378 } | 1322 case LanguageSimpleStyle: { |
| 1379 case NoneListStyle: | 1323 // For these styles, we have some kind of a language-specific separating |
| 1380 return IntRect(); | 1324 // character, followed by a space character to provide sufficient |
| 1381 case ArabicIndic: | 1325 // separation between the list marker text and the associated list item text. |
| 1382 case Armenian: | 1326 UChar suffixSpace[2] = { listMarkerSuffix(style()->listStyleType(), m_li stItem->value()), ' ' }; |
| 1383 case Bengali: | 1327 LayoutUnit itemWidth = getWidthOfTextWithSuffix(suffixSpace, 2); |
| 1384 case Cambodian: | 1328 relativeRect = IntRect(0, 0, itemWidth, style()->font().fontMetrics().he ight()); |
| 1385 case CJKIdeographic: | 1329 } |
| 1386 case CjkEarthlyBranch: | 1330 break; |
| 1387 case CjkHeavenlyStem: | |
| 1388 case DecimalLeadingZero: | |
| 1389 case DecimalListStyle: | |
| 1390 case Devanagari: | |
| 1391 case EthiopicHalehame: | |
| 1392 case EthiopicHalehameAm: | |
| 1393 case EthiopicHalehameTiEr: | |
| 1394 case EthiopicHalehameTiEt: | |
| 1395 case Georgian: | |
| 1396 case Gujarati: | |
| 1397 case Gurmukhi: | |
| 1398 case Hangul: | |
| 1399 case KoreanHangulFormal: | |
| 1400 case KoreanHanjaFormal: | |
| 1401 case KoreanHanjaInformal: | |
| 1402 case HangulConsonant: | |
| 1403 case Hebrew: | |
| 1404 case Hiragana: | |
| 1405 case HiraganaIroha: | |
| 1406 case Kannada: | |
| 1407 case Katakana: | |
| 1408 case KatakanaIroha: | |
| 1409 case Khmer: | |
| 1410 case Lao: | |
| 1411 case LowerAlpha: | |
| 1412 case LowerArmenian: | |
| 1413 case LowerGreek: | |
| 1414 case LowerLatin: | |
| 1415 case LowerRoman: | |
| 1416 case Malayalam: | |
| 1417 case Mongolian: | |
| 1418 case Myanmar: | |
| 1419 case Oriya: | |
| 1420 case Persian: | |
| 1421 case SimpChineseFormal: | |
| 1422 case SimpChineseInformal: | |
| 1423 case Telugu: | |
| 1424 case Thai: | |
| 1425 case Tibetan: | |
| 1426 case TradChineseFormal: | |
| 1427 case TradChineseInformal: | |
| 1428 case UpperAlpha: | |
| 1429 case UpperArmenian: | |
| 1430 case UpperLatin: | |
| 1431 case UpperRoman: | |
| 1432 case Urdu: | |
| 1433 if (m_text.isEmpty()) | |
| 1434 return IntRect(); | |
| 1435 const Font& font = style()->font(); | |
| 1436 int itemWidth = font.width(m_text); | |
| 1437 UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' }; | |
| 1438 int suffixSpaceWidth = font.width(constructTextRun(font, suffixSpace, 2, styleRef(), style()->direction())); | |
| 1439 relativeRect = IntRect(0, 0, itemWidth + suffixSpaceWidth, font.fontMetr ics().height()); | |
| 1440 } | 1331 } |
| 1441 | 1332 |
| 1442 if (!style()->isHorizontalWritingMode()) { | 1333 if (!style()->isHorizontalWritingMode()) { |
| 1443 relativeRect = relativeRect.transposedRect(); | 1334 relativeRect = relativeRect.transposedRect(); |
| 1444 relativeRect.setX(size().width() - relativeRect.x() - relativeRect.width ()); | 1335 relativeRect.setX(size().width() - relativeRect.x() - relativeRect.width ()); |
| 1445 } | 1336 } |
| 1446 | 1337 |
| 1447 return relativeRect; | 1338 return relativeRect; |
| 1448 } | 1339 } |
| 1449 | 1340 |
| 1450 void LayoutListMarker::setSelectionState(SelectionState state) | 1341 void LayoutListMarker::setSelectionState(SelectionState state) |
| 1451 { | 1342 { |
| 1452 // The selection state for our containing block hierarchy is updated by the base class call. | 1343 // The selection state for our containing block hierarchy is updated by the base class call. |
| 1453 LayoutBox::setSelectionState(state); | 1344 LayoutBox::setSelectionState(state); |
| 1454 | 1345 |
| 1455 if (inlineBoxWrapper() && canUpdateSelectionOnRootLineBoxes()) | 1346 if (inlineBoxWrapper() && canUpdateSelectionOnRootLineBoxes()) |
| 1456 inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone ); | 1347 inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone ); |
| 1457 } | 1348 } |
| 1458 | 1349 |
| 1459 LayoutRect LayoutListMarker::selectionRectForPaintInvalidation(const LayoutBoxMo delObject* paintInvalidationContainer) const | 1350 LayoutRect LayoutListMarker::selectionRectForPaintInvalidation(const LayoutBoxMo delObject* paintInvalidationContainer) const |
| 1460 { | 1351 { |
| 1461 ASSERT(!needsLayout()); | 1352 ASSERT(!needsLayout()); |
| 1462 | 1353 |
| 1463 if (selectionState() == SelectionNone || !inlineBoxWrapper()) | 1354 if (selectionState() == SelectionNone || !inlineBoxWrapper()) |
| 1464 return LayoutRect(); | 1355 return LayoutRect(); |
| 1465 | 1356 |
| 1357 // TODO(wkorman): Make sure the output rect from this method matches what we expect to see. | |
| 1358 | |
| 1466 RootInlineBox& root = inlineBoxWrapper()->root(); | 1359 RootInlineBox& root = inlineBoxWrapper()->root(); |
| 1467 LayoutRect rect(0, root.selectionTop() - location().y(), size().width(), roo t.selectionHeight()); | 1360 LayoutRect rect(0, root.selectionTop() - location().y(), size().width(), roo t.selectionHeight()); |
| 1468 mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, 0); | 1361 mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, 0); |
| 1469 // FIXME: groupedMapping() leaks the squashing abstraction. | 1362 // FIXME: groupedMapping() leaks the squashing abstraction. |
| 1470 if (paintInvalidationContainer->layer()->groupedMapping()) | 1363 if (paintInvalidationContainer->layer()->groupedMapping()) |
| 1471 PaintLayer::mapRectToPaintBackingCoordinates(paintInvalidationContainer, rect); | 1364 PaintLayer::mapRectToPaintBackingCoordinates(paintInvalidationContainer, rect); |
| 1472 return rect; | 1365 return rect; |
| 1473 } | 1366 } |
| 1474 | 1367 |
| 1475 void LayoutListMarker::listItemStyleDidChange() | 1368 void LayoutListMarker::listItemStyleDidChange() |
| 1476 { | 1369 { |
| 1477 RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); | 1370 RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); |
| 1478 // The marker always inherits from the list item, regardless of where it mig ht end | 1371 // The marker always inherits from the list item, regardless of where it mig ht end |
| 1479 // up (e.g., in some deeply nested line box). See CSS3 spec. | 1372 // up (e.g., in some deeply nested line box). See CSS3 spec. |
| 1480 newStyle->inheritFrom(m_listItem->styleRef()); | 1373 newStyle->inheritFrom(m_listItem->styleRef()); |
| 1481 if (style()) { | 1374 if (style()) { |
| 1482 // Reuse the current margins. Otherwise resetting the margins to initial values | 1375 // Reuse the current margins. Otherwise resetting the margins to initial values |
| 1483 // would trigger unnecessary layout. | 1376 // would trigger unnecessary layout. |
| 1484 newStyle->setMarginStart(style()->marginStart()); | 1377 newStyle->setMarginStart(style()->marginStart()); |
| 1485 newStyle->setMarginEnd(style()->marginRight()); | 1378 newStyle->setMarginEnd(style()->marginRight()); |
| 1486 } | 1379 } |
| 1487 setStyle(newStyle.release()); | 1380 setStyle(newStyle.release()); |
| 1488 } | 1381 } |
| 1489 | 1382 |
| 1490 } // namespace blink | 1383 } // namespace blink |
| OLD | NEW |