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 |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 18 * You should have received a copy of the GNU Library General Public License |
19 * along with this library; see the file COPYING.LIB. If not, write to | 19 * along with this library; see the file COPYING.LIB. If not, write to |
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #include "core/rendering/RenderListMarker.h" | 26 #include "core/rendering/RenderListMarker.h" |
27 | 27 |
28 #include "core/fetch/ImageResource.h" | 28 #include "core/fetch/ImageResource.h" |
29 #include "core/rendering/GraphicsContextAnnotator.h" | 29 #include "core/paint/ListMarkerPainter.h" |
30 #include "core/rendering/RenderLayer.h" | 30 #include "core/rendering/RenderLayer.h" |
31 #include "core/rendering/RenderListItem.h" | 31 #include "core/rendering/RenderListItem.h" |
32 #include "core/rendering/TextRunConstructor.h" | 32 #include "core/rendering/TextRunConstructor.h" |
33 #include "platform/fonts/Font.h" | 33 #include "platform/fonts/Font.h" |
34 #include "platform/graphics/GraphicsContextStateSaver.h" | |
35 #include "wtf/text/StringBuilder.h" | 34 #include "wtf/text/StringBuilder.h" |
36 #include "wtf/unicode/CharacterNames.h" | |
37 | |
38 using namespace WTF; | |
39 using namespace Unicode; | |
40 | 35 |
41 namespace blink { | 36 namespace blink { |
42 | 37 |
43 const int cMarkerPadding = 7; | 38 const int cMarkerPadding = 7; |
44 | 39 |
45 enum SequenceType { NumericSequence, AlphabeticSequence }; | 40 enum SequenceType { NumericSequence, AlphabeticSequence }; |
46 | 41 |
47 static String toRoman(int number, bool upper) | 42 static String toRoman(int number, bool upper) |
48 { | 43 { |
49 // FIXME: CSS3 describes how to make this work for much larger numbers, | 44 // FIXME: CSS3 describes how to make this work for much larger numbers, |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 case UpperGreek: | 490 case UpperGreek: |
496 case UpperLatin: | 491 case UpperLatin: |
497 case UpperNorwegian: | 492 case UpperNorwegian: |
498 return (value < 1) ? DecimalListStyle : type; | 493 return (value < 1) ? DecimalListStyle : type; |
499 } | 494 } |
500 | 495 |
501 ASSERT_NOT_REACHED(); | 496 ASSERT_NOT_REACHED(); |
502 return type; | 497 return type; |
503 } | 498 } |
504 | 499 |
505 static UChar listMarkerSuffix(EListStyleType type, int value) | 500 UChar RenderListMarker::listMarkerSuffix(EListStyleType type, int value) |
506 { | 501 { |
507 // If the list-style-type cannot represent |value| because it's outside its | 502 // If the list-style-type cannot represent |value| because it's outside its |
508 // ordinal range then we fall back to some list style that can represent |va
lue|. | 503 // ordinal range then we fall back to some list style that can represent |va
lue|. |
509 EListStyleType effectiveType = effectiveListMarkerType(type, value); | 504 EListStyleType effectiveType = effectiveListMarkerType(type, value); |
510 | 505 |
511 // Note, the following switch statement has been explicitly | 506 // Note, the following switch statement has been explicitly |
512 // grouped by list-style-type suffix. | 507 // grouped by list-style-type suffix. |
513 switch (effectiveType) { | 508 switch (effectiveType) { |
514 case Asterisks: | 509 case Asterisks: |
515 case Circle: | 510 case Circle: |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 return LayoutRect(LayoutPoint(), size()); | 1121 return LayoutRect(LayoutPoint(), size()); |
1127 RootInlineBox& root = inlineBoxWrapper()->root(); | 1122 RootInlineBox& root = inlineBoxWrapper()->root(); |
1128 LayoutUnit newLogicalTop = root.block().style()->isFlippedBlocksWritingMode(
) ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() : root.selectio
nTop() - inlineBoxWrapper()->logicalTop(); | 1123 LayoutUnit newLogicalTop = root.block().style()->isFlippedBlocksWritingMode(
) ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() : root.selectio
nTop() - inlineBoxWrapper()->logicalTop(); |
1129 if (root.block().style()->isHorizontalWritingMode()) | 1124 if (root.block().style()->isHorizontalWritingMode()) |
1130 return LayoutRect(0, newLogicalTop, width(), root.selectionHeight()); | 1125 return LayoutRect(0, newLogicalTop, width(), root.selectionHeight()); |
1131 return LayoutRect(newLogicalTop, 0, root.selectionHeight(), height()); | 1126 return LayoutRect(newLogicalTop, 0, root.selectionHeight(), height()); |
1132 } | 1127 } |
1133 | 1128 |
1134 void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
t) | 1129 void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
t) |
1135 { | 1130 { |
1136 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this); | 1131 ListMarkerPainter(*this).paint(paintInfo, paintOffset); |
1137 | |
1138 if (paintInfo.phase != PaintPhaseForeground) | |
1139 return; | |
1140 | |
1141 if (style()->visibility() != VISIBLE) | |
1142 return; | |
1143 | |
1144 LayoutPoint boxOrigin(paintOffset + location()); | |
1145 LayoutRect overflowRect(visualOverflowRect()); | |
1146 overflowRect.moveBy(boxOrigin); | |
1147 | |
1148 if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) | |
1149 return; | |
1150 | |
1151 LayoutRect box(boxOrigin, size()); | |
1152 | |
1153 IntRect marker = getRelativeMarkerRect(); | |
1154 marker.moveBy(roundedIntPoint(boxOrigin)); | |
1155 | |
1156 GraphicsContext* context = paintInfo.context; | |
1157 | |
1158 if (isImage()) { | |
1159 context->drawImage(m_image->image(this, marker.size()).get(), marker); | |
1160 if (selectionState() != SelectionNone) { | |
1161 LayoutRect selRect = localSelectionRect(); | |
1162 selRect.moveBy(boxOrigin); | |
1163 context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundC
olor()); | |
1164 } | |
1165 return; | |
1166 } | |
1167 | |
1168 if (selectionState() != SelectionNone) { | |
1169 LayoutRect selRect = localSelectionRect(); | |
1170 selRect.moveBy(boxOrigin); | |
1171 context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundColor
()); | |
1172 } | |
1173 | |
1174 const Color color(resolveColor(CSSPropertyColor)); | |
1175 context->setStrokeColor(color); | |
1176 context->setStrokeStyle(SolidStroke); | |
1177 context->setStrokeThickness(1.0f); | |
1178 context->setFillColor(color); | |
1179 | |
1180 EListStyleType type = style()->listStyleType(); | |
1181 switch (type) { | |
1182 case Disc: | |
1183 context->fillEllipse(marker); | |
1184 return; | |
1185 case Circle: | |
1186 context->strokeEllipse(marker); | |
1187 return; | |
1188 case Square: | |
1189 context->fillRect(marker); | |
1190 return; | |
1191 case NoneListStyle: | |
1192 return; | |
1193 case Afar: | |
1194 case Amharic: | |
1195 case AmharicAbegede: | |
1196 case ArabicIndic: | |
1197 case Armenian: | |
1198 case BinaryListStyle: | |
1199 case Bengali: | |
1200 case Cambodian: | |
1201 case CJKIdeographic: | |
1202 case CjkEarthlyBranch: | |
1203 case CjkHeavenlyStem: | |
1204 case DecimalLeadingZero: | |
1205 case DecimalListStyle: | |
1206 case Devanagari: | |
1207 case Ethiopic: | |
1208 case EthiopicAbegede: | |
1209 case EthiopicAbegedeAmEt: | |
1210 case EthiopicAbegedeGez: | |
1211 case EthiopicAbegedeTiEr: | |
1212 case EthiopicAbegedeTiEt: | |
1213 case EthiopicHalehameAaEr: | |
1214 case EthiopicHalehameAaEt: | |
1215 case EthiopicHalehameAmEt: | |
1216 case EthiopicHalehameGez: | |
1217 case EthiopicHalehameOmEt: | |
1218 case EthiopicHalehameSidEt: | |
1219 case EthiopicHalehameSoEt: | |
1220 case EthiopicHalehameTiEr: | |
1221 case EthiopicHalehameTiEt: | |
1222 case EthiopicHalehameTig: | |
1223 case Georgian: | |
1224 case Gujarati: | |
1225 case Gurmukhi: | |
1226 case Hangul: | |
1227 case HangulConsonant: | |
1228 case Hebrew: | |
1229 case Hiragana: | |
1230 case HiraganaIroha: | |
1231 case Kannada: | |
1232 case Katakana: | |
1233 case KatakanaIroha: | |
1234 case Khmer: | |
1235 case Lao: | |
1236 case LowerAlpha: | |
1237 case LowerArmenian: | |
1238 case LowerGreek: | |
1239 case LowerHexadecimal: | |
1240 case LowerLatin: | |
1241 case LowerNorwegian: | |
1242 case LowerRoman: | |
1243 case Malayalam: | |
1244 case Mongolian: | |
1245 case Myanmar: | |
1246 case Octal: | |
1247 case Oriya: | |
1248 case Oromo: | |
1249 case Persian: | |
1250 case Sidama: | |
1251 case Somali: | |
1252 case Telugu: | |
1253 case Thai: | |
1254 case Tibetan: | |
1255 case Tigre: | |
1256 case TigrinyaEr: | |
1257 case TigrinyaErAbegede: | |
1258 case TigrinyaEt: | |
1259 case TigrinyaEtAbegede: | |
1260 case UpperAlpha: | |
1261 case UpperArmenian: | |
1262 case UpperGreek: | |
1263 case UpperHexadecimal: | |
1264 case UpperLatin: | |
1265 case UpperNorwegian: | |
1266 case UpperRoman: | |
1267 case Urdu: | |
1268 case Asterisks: | |
1269 case Footnotes: | |
1270 break; | |
1271 } | |
1272 if (m_text.isEmpty()) | |
1273 return; | |
1274 | |
1275 const Font& font = style()->font(); | |
1276 TextRun textRun = constructTextRun(this, font, m_text, style()); | |
1277 | |
1278 GraphicsContextStateSaver stateSaver(*context, false); | |
1279 if (!style()->isHorizontalWritingMode()) { | |
1280 marker.moveBy(roundedIntPoint(-boxOrigin)); | |
1281 marker = marker.transposedRect(); | |
1282 marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - logical
Height()))); | |
1283 stateSaver.save(); | |
1284 context->translate(marker.x(), marker.maxY()); | |
1285 context->rotate(static_cast<float>(deg2rad(90.))); | |
1286 context->translate(-marker.x(), -marker.maxY()); | |
1287 } | |
1288 | |
1289 TextRunPaintInfo textRunPaintInfo(textRun); | |
1290 textRunPaintInfo.bounds = marker; | |
1291 IntPoint textOrigin = IntPoint(marker.x(), marker.y() + style()->fontMetrics
().ascent()); | |
1292 | |
1293 if (type == Asterisks || type == Footnotes) { | |
1294 context->drawText(font, textRunPaintInfo, textOrigin); | |
1295 } | |
1296 else { | |
1297 // Text is not arbitrary. We can judge whether it's RTL from the first c
haracter, | |
1298 // and we only need to handle the direction RightToLeft for now. | |
1299 bool textNeedsReversing = direction(m_text[0]) == RightToLeft; | |
1300 StringBuilder reversedText; | |
1301 if (textNeedsReversing) { | |
1302 int length = m_text.length(); | |
1303 reversedText.reserveCapacity(length); | |
1304 for (int i = length - 1; i >= 0; --i) | |
1305 reversedText.append(m_text[i]); | |
1306 ASSERT(reversedText.length() == reversedText.capacity()); | |
1307 textRun.setText(reversedText.toString()); | |
1308 } | |
1309 | |
1310 const UChar suffix = listMarkerSuffix(type, m_listItem->value()); | |
1311 UChar suffixStr[2] = { | |
1312 style()->isLeftToRightDirection() ? suffix : ' ', | |
1313 style()->isLeftToRightDirection() ? ' ' : suffix | |
1314 }; | |
1315 TextRun suffixRun = constructTextRun(this, font, suffixStr, 2, style(),
style()->direction()); | |
1316 TextRunPaintInfo suffixRunInfo(suffixRun); | |
1317 suffixRunInfo.bounds = marker; | |
1318 | |
1319 if (style()->isLeftToRightDirection()) { | |
1320 context->drawText(font, textRunPaintInfo, textOrigin); | |
1321 context->drawText(font, suffixRunInfo, textOrigin + IntSize(font.wid
th(textRun), 0)); | |
1322 } else { | |
1323 context->drawText(font, suffixRunInfo, textOrigin); | |
1324 context->drawText(font, textRunPaintInfo, textOrigin + IntSize(font.
width(suffixRun), 0)); | |
1325 } | |
1326 } | |
1327 } | 1132 } |
1328 | 1133 |
1329 void RenderListMarker::layout() | 1134 void RenderListMarker::layout() |
1330 { | 1135 { |
1331 ASSERT(needsLayout()); | 1136 ASSERT(needsLayout()); |
1332 | 1137 |
1333 if (isImage()) { | 1138 if (isImage()) { |
1334 updateMarginsAndContent(); | 1139 updateMarginsAndContent(); |
1335 setWidth(m_image->imageSize(this, style()->effectiveZoom()).width()); | 1140 setWidth(m_image->imageSize(this, style()->effectiveZoom()).width()); |
1336 setHeight(m_image->imageSize(this, style()->effectiveZoom()).height()); | 1141 setHeight(m_image->imageSize(this, style()->effectiveZoom()).height()); |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1822 if (selectionState() == SelectionNone || !inlineBoxWrapper()) | 1627 if (selectionState() == SelectionNone || !inlineBoxWrapper()) |
1823 return LayoutRect(); | 1628 return LayoutRect(); |
1824 | 1629 |
1825 RootInlineBox& root = inlineBoxWrapper()->root(); | 1630 RootInlineBox& root = inlineBoxWrapper()->root(); |
1826 LayoutRect rect(0, root.selectionTop() - y(), width(), root.selectionHeight(
)); | 1631 LayoutRect rect(0, root.selectionTop() - y(), width(), root.selectionHeight(
)); |
1827 | 1632 |
1828 return localToContainerQuad(FloatRect(rect), paintInvalidationContainer).enc
losingBoundingBox(); | 1633 return localToContainerQuad(FloatRect(rect), paintInvalidationContainer).enc
losingBoundingBox(); |
1829 } | 1634 } |
1830 | 1635 |
1831 } // namespace blink | 1636 } // namespace blink |
OLD | NEW |