Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutListMarker.cpp

Issue 1403643002: Rework list marker spacing for better web compatibility. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@472084_use_list_item_painter
Patch Set: Fix compile error with default switch case. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698