OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/paint/ListMarkerPainter.h" |
| 7 |
| 8 #include "core/paint/BlockPainter.h" |
| 9 #include "core/rendering/GraphicsContextAnnotator.h" |
| 10 #include "core/rendering/PaintInfo.h" |
| 11 #include "core/rendering/RenderListItem.h" |
| 12 #include "core/rendering/RenderListMarker.h" |
| 13 #include "core/rendering/TextRunConstructor.h" |
| 14 #include "platform/geometry/LayoutPoint.h" |
| 15 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 16 #include "wtf/unicode/CharacterNames.h" |
| 17 |
| 18 namespace blink { |
| 19 |
| 20 void ListMarkerPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffs
et) |
| 21 { |
| 22 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderListMarker); |
| 23 |
| 24 if (paintInfo.phase != PaintPhaseForeground) |
| 25 return; |
| 26 |
| 27 if (m_renderListMarker.style()->visibility() != VISIBLE) |
| 28 return; |
| 29 |
| 30 LayoutPoint boxOrigin(paintOffset + m_renderListMarker.location()); |
| 31 LayoutRect overflowRect(m_renderListMarker.visualOverflowRect()); |
| 32 overflowRect.moveBy(boxOrigin); |
| 33 |
| 34 if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) |
| 35 return; |
| 36 |
| 37 LayoutRect box(boxOrigin, m_renderListMarker.size()); |
| 38 |
| 39 IntRect marker = m_renderListMarker.getRelativeMarkerRect(); |
| 40 marker.moveBy(roundedIntPoint(boxOrigin)); |
| 41 |
| 42 GraphicsContext* context = paintInfo.context; |
| 43 |
| 44 if (m_renderListMarker.isImage()) { |
| 45 context->drawImage(m_renderListMarker.image()->image(&m_renderListMarker
, marker.size()).get(), marker); |
| 46 if (m_renderListMarker.selectionState() != RenderObject::SelectionNone)
{ |
| 47 LayoutRect selRect = m_renderListMarker.localSelectionRect(); |
| 48 selRect.moveBy(boxOrigin); |
| 49 context->fillRect(pixelSnappedIntRect(selRect), m_renderListMarker.s
electionBackgroundColor()); |
| 50 } |
| 51 return; |
| 52 } |
| 53 |
| 54 if (m_renderListMarker.selectionState() != RenderObject::SelectionNone) { |
| 55 LayoutRect selRect = m_renderListMarker.localSelectionRect(); |
| 56 selRect.moveBy(boxOrigin); |
| 57 context->fillRect(pixelSnappedIntRect(selRect), m_renderListMarker.selec
tionBackgroundColor()); |
| 58 } |
| 59 |
| 60 const Color color(m_renderListMarker.resolveColor(CSSPropertyColor)); |
| 61 context->setStrokeColor(color); |
| 62 context->setStrokeStyle(SolidStroke); |
| 63 context->setStrokeThickness(1.0f); |
| 64 context->setFillColor(color); |
| 65 |
| 66 EListStyleType type = m_renderListMarker.style()->listStyleType(); |
| 67 switch (type) { |
| 68 case Disc: |
| 69 context->fillEllipse(marker); |
| 70 return; |
| 71 case Circle: |
| 72 context->strokeEllipse(marker); |
| 73 return; |
| 74 case Square: |
| 75 context->fillRect(marker); |
| 76 return; |
| 77 case NoneListStyle: |
| 78 return; |
| 79 case Afar: |
| 80 case Amharic: |
| 81 case AmharicAbegede: |
| 82 case ArabicIndic: |
| 83 case Armenian: |
| 84 case BinaryListStyle: |
| 85 case Bengali: |
| 86 case Cambodian: |
| 87 case CJKIdeographic: |
| 88 case CjkEarthlyBranch: |
| 89 case CjkHeavenlyStem: |
| 90 case DecimalLeadingZero: |
| 91 case DecimalListStyle: |
| 92 case Devanagari: |
| 93 case Ethiopic: |
| 94 case EthiopicAbegede: |
| 95 case EthiopicAbegedeAmEt: |
| 96 case EthiopicAbegedeGez: |
| 97 case EthiopicAbegedeTiEr: |
| 98 case EthiopicAbegedeTiEt: |
| 99 case EthiopicHalehameAaEr: |
| 100 case EthiopicHalehameAaEt: |
| 101 case EthiopicHalehameAmEt: |
| 102 case EthiopicHalehameGez: |
| 103 case EthiopicHalehameOmEt: |
| 104 case EthiopicHalehameSidEt: |
| 105 case EthiopicHalehameSoEt: |
| 106 case EthiopicHalehameTiEr: |
| 107 case EthiopicHalehameTiEt: |
| 108 case EthiopicHalehameTig: |
| 109 case Georgian: |
| 110 case Gujarati: |
| 111 case Gurmukhi: |
| 112 case Hangul: |
| 113 case HangulConsonant: |
| 114 case Hebrew: |
| 115 case Hiragana: |
| 116 case HiraganaIroha: |
| 117 case Kannada: |
| 118 case Katakana: |
| 119 case KatakanaIroha: |
| 120 case Khmer: |
| 121 case Lao: |
| 122 case LowerAlpha: |
| 123 case LowerArmenian: |
| 124 case LowerGreek: |
| 125 case LowerHexadecimal: |
| 126 case LowerLatin: |
| 127 case LowerNorwegian: |
| 128 case LowerRoman: |
| 129 case Malayalam: |
| 130 case Mongolian: |
| 131 case Myanmar: |
| 132 case Octal: |
| 133 case Oriya: |
| 134 case Oromo: |
| 135 case Persian: |
| 136 case Sidama: |
| 137 case Somali: |
| 138 case Telugu: |
| 139 case Thai: |
| 140 case Tibetan: |
| 141 case Tigre: |
| 142 case TigrinyaEr: |
| 143 case TigrinyaErAbegede: |
| 144 case TigrinyaEt: |
| 145 case TigrinyaEtAbegede: |
| 146 case UpperAlpha: |
| 147 case UpperArmenian: |
| 148 case UpperGreek: |
| 149 case UpperHexadecimal: |
| 150 case UpperLatin: |
| 151 case UpperNorwegian: |
| 152 case UpperRoman: |
| 153 case Urdu: |
| 154 case Asterisks: |
| 155 case Footnotes: |
| 156 break; |
| 157 } |
| 158 if (m_renderListMarker.text().isEmpty()) |
| 159 return; |
| 160 |
| 161 const Font& font = m_renderListMarker.style()->font(); |
| 162 TextRun textRun = constructTextRun(&m_renderListMarker, font, m_renderListMa
rker.text(), m_renderListMarker.style()); |
| 163 |
| 164 GraphicsContextStateSaver stateSaver(*context, false); |
| 165 if (!m_renderListMarker.style()->isHorizontalWritingMode()) { |
| 166 marker.moveBy(roundedIntPoint(-boxOrigin)); |
| 167 marker = marker.transposedRect(); |
| 168 marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - m_rende
rListMarker.logicalHeight()))); |
| 169 stateSaver.save(); |
| 170 context->translate(marker.x(), marker.maxY()); |
| 171 context->rotate(static_cast<float>(deg2rad(90.))); |
| 172 context->translate(-marker.x(), -marker.maxY()); |
| 173 } |
| 174 |
| 175 TextRunPaintInfo textRunPaintInfo(textRun); |
| 176 textRunPaintInfo.bounds = marker; |
| 177 IntPoint textOrigin = IntPoint(marker.x(), marker.y() + m_renderListMarker.s
tyle()->fontMetrics().ascent()); |
| 178 |
| 179 if (type == Asterisks || type == Footnotes) { |
| 180 context->drawText(font, textRunPaintInfo, textOrigin); |
| 181 } else { |
| 182 // Text is not arbitrary. We can judge whether it's RTL from the first c
haracter, |
| 183 // and we only need to handle the direction RightToLeft for now. |
| 184 bool textNeedsReversing = WTF::Unicode::direction(m_renderListMarker.tex
t()[0]) == WTF::Unicode::RightToLeft; |
| 185 StringBuilder reversedText; |
| 186 if (textNeedsReversing) { |
| 187 int length = m_renderListMarker.text().length(); |
| 188 reversedText.reserveCapacity(length); |
| 189 for (int i = length - 1; i >= 0; --i) |
| 190 reversedText.append(m_renderListMarker.text()[i]); |
| 191 ASSERT(reversedText.length() == reversedText.capacity()); |
| 192 textRun.setText(reversedText.toString()); |
| 193 } |
| 194 |
| 195 const UChar suffix = m_renderListMarker.listMarkerSuffix(type, m_renderL
istMarker.listItem()->value()); |
| 196 UChar suffixStr[2] = { |
| 197 m_renderListMarker.style()->isLeftToRightDirection() ? suffix : ' ', |
| 198 m_renderListMarker.style()->isLeftToRightDirection() ? ' ' : suffix |
| 199 }; |
| 200 TextRun suffixRun = constructTextRun(&m_renderListMarker, font, suffixSt
r, 2, m_renderListMarker.style(), m_renderListMarker.style()->direction()); |
| 201 TextRunPaintInfo suffixRunInfo(suffixRun); |
| 202 suffixRunInfo.bounds = marker; |
| 203 |
| 204 if (m_renderListMarker.style()->isLeftToRightDirection()) { |
| 205 context->drawText(font, textRunPaintInfo, textOrigin); |
| 206 context->drawText(font, suffixRunInfo, textOrigin + IntSize(font.wid
th(textRun), 0)); |
| 207 } else { |
| 208 context->drawText(font, suffixRunInfo, textOrigin); |
| 209 context->drawText(font, textRunPaintInfo, textOrigin + IntSize(font.
width(suffixRun), 0)); |
| 210 } |
| 211 } |
| 212 } |
| 213 |
| 214 } // namespace blink |
OLD | NEW |