OLD | NEW |
1 /** | 1 /** |
2 * Copyright (C) 2007 Rob Buis <buis@kde.org> | 2 * Copyright (C) 2007 Rob Buis <buis@kde.org> |
3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
4 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 | 48 |
49 struct ExpectedSVGInlineTextBoxSize : public InlineTextBox { | 49 struct ExpectedSVGInlineTextBoxSize : public InlineTextBox { |
50 float float1; | 50 float float1; |
51 uint32_t bitfields : 5; | 51 uint32_t bitfields : 5; |
52 void* pointer; | 52 void* pointer; |
53 Vector<SVGTextFragment> vector; | 53 Vector<SVGTextFragment> vector; |
54 }; | 54 }; |
55 | 55 |
56 COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize),
SVGInlineTextBox_is_not_of_expected_size); | 56 COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize),
SVGInlineTextBox_is_not_of_expected_size); |
57 | 57 |
58 SVGInlineTextBox::SVGInlineTextBox(RenderObject* object) | 58 SVGInlineTextBox::SVGInlineTextBox(RenderObject& object) |
59 : InlineTextBox(object) | 59 : InlineTextBox(object) |
60 , m_logicalHeight(0) | 60 , m_logicalHeight(0) |
61 , m_paintingResourceMode(ApplyToDefaultMode) | 61 , m_paintingResourceMode(ApplyToDefaultMode) |
62 , m_startsNewTextChunk(false) | 62 , m_startsNewTextChunk(false) |
63 , m_paintingResource(0) | 63 , m_paintingResource(0) |
64 { | 64 { |
65 } | 65 } |
66 | 66 |
67 void SVGInlineTextBox::dirtyLineBoxes() | 67 void SVGInlineTextBox::dirtyLineBoxes() |
68 { | 68 { |
(...skipping 12 matching lines...) Expand all Loading... |
81 int SVGInlineTextBox::offsetForPosition(float, bool) const | 81 int SVGInlineTextBox::offsetForPosition(float, bool) const |
82 { | 82 { |
83 // SVG doesn't use the standard offset <-> position selection system, as it'
s not suitable for SVGs complex needs. | 83 // SVG doesn't use the standard offset <-> position selection system, as it'
s not suitable for SVGs complex needs. |
84 // vertical text selection, inline boxes spanning multiple lines (contrary t
o HTML, etc.) | 84 // vertical text selection, inline boxes spanning multiple lines (contrary t
o HTML, etc.) |
85 ASSERT_NOT_REACHED(); | 85 ASSERT_NOT_REACHED(); |
86 return 0; | 86 return 0; |
87 } | 87 } |
88 | 88 |
89 int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
t, float position, bool includePartialGlyphs) const | 89 int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
t, float position, bool includePartialGlyphs) const |
90 { | 90 { |
91 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 91 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
92 ASSERT(textRenderer); | |
93 | 92 |
94 float scalingFactor = textRenderer->scalingFactor(); | 93 float scalingFactor = textRenderer.scalingFactor(); |
95 ASSERT(scalingFactor); | 94 ASSERT(scalingFactor); |
96 | 95 |
97 RenderStyle* style = textRenderer->style(); | 96 RenderStyle* style = textRenderer.style(); |
98 ASSERT(style); | 97 ASSERT(style); |
99 | 98 |
100 TextRun textRun = constructTextRun(style, fragment); | 99 TextRun textRun = constructTextRun(style, fragment); |
101 | 100 |
102 // Eventually handle lengthAdjust="spacingAndGlyphs". | 101 // Eventually handle lengthAdjust="spacingAndGlyphs". |
103 // FIXME: Handle vertical text. | 102 // FIXME: Handle vertical text. |
104 AffineTransform fragmentTransform; | 103 AffineTransform fragmentTransform; |
105 fragment.buildFragmentTransform(fragmentTransform); | 104 fragment.buildFragmentTransform(fragmentTransform); |
106 if (!fragmentTransform.isIdentity()) | 105 if (!fragmentTransform.isIdentity()) |
107 textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransfo
rm.xScale())); | 106 textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransfo
rm.xScale())); |
108 | 107 |
109 return fragment.characterOffset - start() + textRenderer->scaledFont().offse
tForPosition(textRun, position * scalingFactor, includePartialGlyphs); | 108 return fragment.characterOffset - start() + textRenderer.scaledFont().offset
ForPosition(textRun, position * scalingFactor, includePartialGlyphs); |
110 } | 109 } |
111 | 110 |
112 float SVGInlineTextBox::positionForOffset(int) const | 111 float SVGInlineTextBox::positionForOffset(int) const |
113 { | 112 { |
114 // SVG doesn't use the offset <-> position selection system. | 113 // SVG doesn't use the offset <-> position selection system. |
115 ASSERT_NOT_REACHED(); | 114 ASSERT_NOT_REACHED(); |
116 return 0; | 115 return 0; |
117 } | 116 } |
118 | 117 |
119 FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
fragment, int startPosition, int endPosition, RenderStyle* style) | 118 FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
fragment, int startPosition, int endPosition, RenderStyle* style) |
120 { | 119 { |
121 ASSERT(startPosition < endPosition); | 120 ASSERT(startPosition < endPosition); |
122 ASSERT(style); | 121 ASSERT(style); |
123 | 122 |
124 FontCachePurgePreventer fontCachePurgePreventer; | 123 FontCachePurgePreventer fontCachePurgePreventer; |
125 | 124 |
126 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 125 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
127 ASSERT(textRenderer); | |
128 | 126 |
129 float scalingFactor = textRenderer->scalingFactor(); | 127 float scalingFactor = textRenderer.scalingFactor(); |
130 ASSERT(scalingFactor); | 128 ASSERT(scalingFactor); |
131 | 129 |
132 const Font& scaledFont = textRenderer->scaledFont(); | 130 const Font& scaledFont = textRenderer.scaledFont(); |
133 const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); | 131 const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); |
134 FloatPoint textOrigin(fragment.x, fragment.y); | 132 FloatPoint textOrigin(fragment.x, fragment.y); |
135 if (scalingFactor != 1) | 133 if (scalingFactor != 1) |
136 textOrigin.scale(scalingFactor, scalingFactor); | 134 textOrigin.scale(scalingFactor, scalingFactor); |
137 | 135 |
138 textOrigin.move(0, -scaledFontMetrics.floatAscent()); | 136 textOrigin.move(0, -scaledFontMetrics.floatAscent()); |
139 | 137 |
140 FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(s
tyle, fragment), textOrigin, fragment.height * scalingFactor, startPosition, end
Position); | 138 FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(s
tyle, fragment), textOrigin, fragment.height * scalingFactor, startPosition, end
Position); |
141 if (scalingFactor == 1) | 139 if (scalingFactor == 1) |
142 return selectionRect; | 140 return selectionRect; |
143 | 141 |
144 selectionRect.scale(1 / scalingFactor); | 142 selectionRect.scale(1 / scalingFactor); |
145 return selectionRect; | 143 return selectionRect; |
146 } | 144 } |
147 | 145 |
148 LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
on) | 146 LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
on) |
149 { | 147 { |
150 int boxStart = start(); | 148 int boxStart = start(); |
151 startPosition = max(startPosition - boxStart, 0); | 149 startPosition = max(startPosition - boxStart, 0); |
152 endPosition = min(endPosition - boxStart, static_cast<int>(len())); | 150 endPosition = min(endPosition - boxStart, static_cast<int>(len())); |
153 if (startPosition >= endPosition) | 151 if (startPosition >= endPosition) |
154 return LayoutRect(); | 152 return LayoutRect(); |
155 | 153 |
156 RenderText* text = textRenderer(); | 154 RenderStyle* style = textRenderer().style(); |
157 ASSERT(text); | |
158 | |
159 RenderStyle* style = text->style(); | |
160 ASSERT(style); | 155 ASSERT(style); |
161 | 156 |
162 AffineTransform fragmentTransform; | 157 AffineTransform fragmentTransform; |
163 FloatRect selectionRect; | 158 FloatRect selectionRect; |
164 int fragmentStartPosition = 0; | 159 int fragmentStartPosition = 0; |
165 int fragmentEndPosition = 0; | 160 int fragmentEndPosition = 0; |
166 | 161 |
167 unsigned textFragmentsSize = m_textFragments.size(); | 162 unsigned textFragmentsSize = m_textFragments.size(); |
168 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 163 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
169 const SVGTextFragment& fragment = m_textFragments.at(i); | 164 const SVGTextFragment& fragment = m_textFragments.at(i); |
170 | 165 |
171 fragmentStartPosition = startPosition; | 166 fragmentStartPosition = startPosition; |
172 fragmentEndPosition = endPosition; | 167 fragmentEndPosition = endPosition; |
173 if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStart
Position, fragmentEndPosition)) | 168 if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStart
Position, fragmentEndPosition)) |
174 continue; | 169 continue; |
175 | 170 |
176 FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragment
StartPosition, fragmentEndPosition, style); | 171 FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragment
StartPosition, fragmentEndPosition, style); |
177 fragment.buildFragmentTransform(fragmentTransform); | 172 fragment.buildFragmentTransform(fragmentTransform); |
178 fragmentRect = fragmentTransform.mapRect(fragmentRect); | 173 fragmentRect = fragmentTransform.mapRect(fragmentRect); |
179 | 174 |
180 selectionRect.unite(fragmentRect); | 175 selectionRect.unite(fragmentRect); |
181 } | 176 } |
182 | 177 |
183 return enclosingIntRect(selectionRect); | 178 return enclosingIntRect(selectionRect); |
184 } | 179 } |
185 | 180 |
186 static inline bool textShouldBePainted(RenderSVGInlineText* textRenderer) | 181 static inline bool textShouldBePainted(RenderSVGInlineText& textRenderer) |
187 { | 182 { |
188 // Font::pixelSize(), returns FontDescription::computedPixelSize(), which re
turns "int(x + 0.5)". | 183 // Font::pixelSize(), returns FontDescription::computedPixelSize(), which re
turns "int(x + 0.5)". |
189 // If the absolute font size on screen is below x=0.5, don't render anything
. | 184 // If the absolute font size on screen is below x=0.5, don't render anything
. |
190 return textRenderer->scaledFont().fontDescription().computedPixelSize(); | 185 return textRenderer.scaledFont().fontDescription().computedPixelSize(); |
191 } | 186 } |
192 | 187 |
193 void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) | 188 void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) |
194 { | 189 { |
195 ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); | 190 ASSERT(paintInfo.shouldPaintWithinRoot(&renderer())); |
196 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPh
aseSelection); | 191 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPh
aseSelection); |
197 ASSERT(truncation() == cNoTruncation); | 192 ASSERT(truncation() == cNoTruncation); |
198 | 193 |
199 if (renderer()->style()->visibility() != VISIBLE) | 194 if (renderer().style()->visibility() != VISIBLE) |
200 return; | 195 return; |
201 | 196 |
202 RenderObject* parentRenderer = parent()->renderer(); | 197 RenderObject& parentRenderer = parent()->renderer(); |
203 ASSERT(parentRenderer); | 198 ASSERT(!parentRenderer.document().printing()); |
204 ASSERT(!parentRenderer->document().printing()); | |
205 | 199 |
206 // Determine whether or not we're selected. | 200 // Determine whether or not we're selected. |
207 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; | 201 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; |
208 bool hasSelection = selectionState() != RenderObject::SelectionNone; | 202 bool hasSelection = selectionState() != RenderObject::SelectionNone; |
209 if (!hasSelection || paintSelectedTextOnly) | 203 if (!hasSelection || paintSelectedTextOnly) |
210 return; | 204 return; |
211 | 205 |
212 Color backgroundColor = renderer()->selectionBackgroundColor(); | 206 Color backgroundColor = renderer().selectionBackgroundColor(); |
213 if (!backgroundColor.alpha()) | 207 if (!backgroundColor.alpha()) |
214 return; | 208 return; |
215 | 209 |
216 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 210 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
217 ASSERT(textRenderer); | |
218 if (!textShouldBePainted(textRenderer)) | 211 if (!textShouldBePainted(textRenderer)) |
219 return; | 212 return; |
220 | 213 |
221 RenderStyle* style = parentRenderer->style(); | 214 RenderStyle* style = parentRenderer.style(); |
222 ASSERT(style); | 215 ASSERT(style); |
223 | 216 |
224 int startPosition, endPosition; | 217 int startPosition, endPosition; |
225 selectionStartEnd(startPosition, endPosition); | 218 selectionStartEnd(startPosition, endPosition); |
226 | 219 |
227 int fragmentStartPosition = 0; | 220 int fragmentStartPosition = 0; |
228 int fragmentEndPosition = 0; | 221 int fragmentEndPosition = 0; |
229 AffineTransform fragmentTransform; | 222 AffineTransform fragmentTransform; |
230 unsigned textFragmentsSize = m_textFragments.size(); | 223 unsigned textFragmentsSize = m_textFragments.size(); |
231 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 224 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
(...skipping 14 matching lines...) Expand all Loading... |
246 paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragm
entStartPosition, fragmentEndPosition, style), backgroundColor); | 239 paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragm
entStartPosition, fragmentEndPosition, style), backgroundColor); |
247 | 240 |
248 m_paintingResourceMode = ApplyToDefaultMode; | 241 m_paintingResourceMode = ApplyToDefaultMode; |
249 } | 242 } |
250 | 243 |
251 ASSERT(!m_paintingResource); | 244 ASSERT(!m_paintingResource); |
252 } | 245 } |
253 | 246 |
254 void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
t, LayoutUnit, LayoutUnit) | 247 void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
t, LayoutUnit, LayoutUnit) |
255 { | 248 { |
256 ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); | 249 ASSERT(paintInfo.shouldPaintWithinRoot(&renderer())); |
257 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPh
aseSelection); | 250 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPh
aseSelection); |
258 ASSERT(truncation() == cNoTruncation); | 251 ASSERT(truncation() == cNoTruncation); |
259 | 252 |
260 if (renderer()->style()->visibility() != VISIBLE) | 253 if (renderer().style()->visibility() != VISIBLE) |
261 return; | 254 return; |
262 | 255 |
263 // Note: We're explicitely not supporting composition & custom underlines an
d custom highlighters - unlike InlineTextBox. | 256 // Note: We're explicitely not supporting composition & custom underlines an
d custom highlighters - unlike InlineTextBox. |
264 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. | 257 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. |
265 | 258 |
266 RenderObject* parentRenderer = parent()->renderer(); | 259 RenderObject& parentRenderer = parent()->renderer(); |
267 ASSERT(parentRenderer); | |
268 | 260 |
269 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; | 261 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; |
270 bool hasSelection = !parentRenderer->document().printing() && selectionState
() != RenderObject::SelectionNone; | 262 bool hasSelection = !parentRenderer.document().printing() && selectionState(
) != RenderObject::SelectionNone; |
271 if (!hasSelection && paintSelectedTextOnly) | 263 if (!hasSelection && paintSelectedTextOnly) |
272 return; | 264 return; |
273 | 265 |
274 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 266 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
275 ASSERT(textRenderer); | |
276 if (!textShouldBePainted(textRenderer)) | 267 if (!textShouldBePainted(textRenderer)) |
277 return; | 268 return; |
278 | 269 |
279 RenderStyle* style = parentRenderer->style(); | 270 RenderStyle* style = parentRenderer.style(); |
280 ASSERT(style); | 271 ASSERT(style); |
281 | 272 |
282 paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer->sc
aledFont(), true); | 273 paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.sca
ledFont(), true); |
283 | 274 |
284 const SVGRenderStyle* svgStyle = style->svgStyle(); | 275 const SVGRenderStyle* svgStyle = style->svgStyle(); |
285 ASSERT(svgStyle); | 276 ASSERT(svgStyle); |
286 | 277 |
287 bool hasFill = svgStyle->hasFill(); | 278 bool hasFill = svgStyle->hasFill(); |
288 bool hasVisibleStroke = svgStyle->hasVisibleStroke(); | 279 bool hasVisibleStroke = svgStyle->hasVisibleStroke(); |
289 | 280 |
290 RenderStyle* selectionStyle = style; | 281 RenderStyle* selectionStyle = style; |
291 if (hasSelection) { | 282 if (hasSelection) { |
292 selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION); | 283 selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION); |
293 if (selectionStyle) { | 284 if (selectionStyle) { |
294 const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle()
; | 285 const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle()
; |
295 ASSERT(svgSelectionStyle); | 286 ASSERT(svgSelectionStyle); |
296 | 287 |
297 if (!hasFill) | 288 if (!hasFill) |
298 hasFill = svgSelectionStyle->hasFill(); | 289 hasFill = svgSelectionStyle->hasFill(); |
299 if (!hasVisibleStroke) | 290 if (!hasVisibleStroke) |
300 hasVisibleStroke = svgSelectionStyle->hasVisibleStroke(); | 291 hasVisibleStroke = svgSelectionStyle->hasVisibleStroke(); |
301 } else | 292 } else |
302 selectionStyle = style; | 293 selectionStyle = style; |
303 } | 294 } |
304 | 295 |
305 if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->
frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) { | 296 if (textRenderer.frame() && textRenderer.frame()->view() && textRenderer.fra
me()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) { |
306 hasFill = true; | 297 hasFill = true; |
307 hasVisibleStroke = false; | 298 hasVisibleStroke = false; |
308 } | 299 } |
309 | 300 |
310 AffineTransform fragmentTransform; | 301 AffineTransform fragmentTransform; |
311 unsigned textFragmentsSize = m_textFragments.size(); | 302 unsigned textFragmentsSize = m_textFragments.size(); |
312 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 303 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
313 SVGTextFragment& fragment = m_textFragments.at(i); | 304 SVGTextFragment& fragment = m_textFragments.at(i); |
314 ASSERT(!m_paintingResource); | 305 ASSERT(!m_paintingResource); |
315 | 306 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode) | 384 if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode) |
394 context->setStrokeThickness(context->strokeThickness() * scalingFactor); | 385 context->setStrokeThickness(context->strokeThickness() * scalingFactor); |
395 | 386 |
396 return true; | 387 return true; |
397 } | 388 } |
398 | 389 |
399 void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const
Path* path) | 390 void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const
Path* path) |
400 { | 391 { |
401 ASSERT(m_paintingResource); | 392 ASSERT(m_paintingResource); |
402 | 393 |
403 RenderObject* parentRenderer = parent()->renderer(); | 394 m_paintingResource->postApplyResource(&parent()->renderer(), context, m_pain
tingResourceMode, path, /*RenderSVGShape*/ 0); |
404 ASSERT(parentRenderer); | |
405 | |
406 m_paintingResource->postApplyResource(parentRenderer, context, m_paintingRes
ourceMode, path, /*RenderSVGShape*/ 0); | |
407 m_paintingResource = 0; | 395 m_paintingResource = 0; |
408 } | 396 } |
409 | 397 |
410 bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c
ontext, float scalingFactor, TextRun& textRun, RenderStyle* style) | 398 bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c
ontext, float scalingFactor, TextRun& textRun, RenderStyle* style) |
411 { | 399 { |
412 bool acquiredResource = acquirePaintingResource(context, scalingFactor, pare
nt()->renderer(), style); | 400 bool acquiredResource = acquirePaintingResource(context, scalingFactor, &par
ent()->renderer(), style); |
413 if (!acquiredResource) | 401 if (!acquiredResource) |
414 return false; | 402 return false; |
415 | 403 |
416 #if ENABLE(SVG_FONTS) | 404 #if ENABLE(SVG_FONTS) |
417 // SVG Fonts need access to the painting resource used to draw the current t
ext chunk. | 405 // SVG Fonts need access to the painting resource used to draw the current t
ext chunk. |
418 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); | 406 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); |
419 if (renderingContext) | 407 if (renderingContext) |
420 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(m_paintingResource); | 408 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(m_paintingResource); |
421 #endif | 409 #endif |
422 | 410 |
423 return true; | 411 return true; |
424 } | 412 } |
425 | 413 |
426 void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*&
context, TextRun& textRun) | 414 void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*&
context, TextRun& textRun) |
427 { | 415 { |
428 releasePaintingResource(context, /* path */0); | 416 releasePaintingResource(context, /* path */0); |
429 | 417 |
430 #if ENABLE(SVG_FONTS) | 418 #if ENABLE(SVG_FONTS) |
431 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); | 419 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); |
432 if (renderingContext) | 420 if (renderingContext) |
433 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(0); | 421 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(0); |
434 #endif | 422 #endif |
435 } | 423 } |
436 | 424 |
437 TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
ment& fragment) const | 425 TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
ment& fragment) const |
438 { | 426 { |
439 ASSERT(style); | 427 ASSERT(style); |
440 ASSERT(textRenderer()); | |
441 | 428 |
442 RenderText* text = textRenderer(); | 429 RenderText* text = &textRenderer(); |
443 ASSERT(text); | |
444 | 430 |
445 // FIXME(crbug.com/264211): This should not be necessary but can occur if we | 431 // FIXME(crbug.com/264211): This should not be necessary but can occur if we |
446 // layout during layout. Remove this when 264211 is
fixed. | 432 // layout during layout. Remove this when 264211 is
fixed. |
447 RELEASE_ASSERT(!text->needsLayout()); | 433 RELEASE_ASSERT(!text->needsLayout()); |
448 | 434 |
449 TextRun run(static_cast<const LChar*>(0) // characters, will be set below if
non-zero. | 435 TextRun run(static_cast<const LChar*>(0) // characters, will be set below if
non-zero. |
450 , 0 // length, will be set below if non-zero. | 436 , 0 // length, will be set below if non-zero. |
451 , 0 // xPos, only relevant with allowTabs=true | 437 , 0 // xPos, only relevant with allowTabs=true |
452 , 0 // padding, only relevant for justified text, not relevant f
or SVG | 438 , 0 // padding, only relevant for justified text, not relevant f
or SVG |
453 , TextRun::AllowTrailingExpansion | 439 , TextRun::AllowTrailingExpansion |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. | 508 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. |
523 // Compatible with Batik/Opera | 509 // Compatible with Batik/Opera |
524 return font.fontDescription().computedSize() / 20.0f; | 510 return font.fontDescription().computedSize() / 20.0f; |
525 } | 511 } |
526 | 512 |
527 static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
ox* parentBox) | 513 static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
ox* parentBox) |
528 { | 514 { |
529 // Lookup first render object in parent hierarchy which has text-decoration
set. | 515 // Lookup first render object in parent hierarchy which has text-decoration
set. |
530 RenderObject* renderer = 0; | 516 RenderObject* renderer = 0; |
531 while (parentBox) { | 517 while (parentBox) { |
532 renderer = parentBox->renderer(); | 518 renderer = &parentBox->renderer(); |
533 | 519 |
534 if (renderer->style() && renderer->style()->textDecoration() != TextDeco
rationNone) | 520 if (renderer->style() && renderer->style()->textDecoration() != TextDeco
rationNone) |
535 break; | 521 break; |
536 | 522 |
537 parentBox = parentBox->parent(); | 523 parentBox = parentBox->parent(); |
538 } | 524 } |
539 | 525 |
540 ASSERT(renderer); | 526 ASSERT(renderer); |
541 return renderer; | 527 return renderer; |
542 } | 528 } |
543 | 529 |
544 void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
decoration, const SVGTextFragment& fragment) | 530 void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
decoration, const SVGTextFragment& fragment) |
545 { | 531 { |
546 if (textRenderer()->style()->textDecorationsInEffect() == TextDecorationNone
) | 532 if (textRenderer().style()->textDecorationsInEffect() == TextDecorationNone) |
547 return; | 533 return; |
548 | 534 |
549 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. | 535 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. |
550 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
parent()); | 536 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
parent()); |
551 RenderStyle* decorationStyle = decorationRenderer->style(); | 537 RenderStyle* decorationStyle = decorationRenderer->style(); |
552 ASSERT(decorationStyle); | 538 ASSERT(decorationStyle); |
553 | 539 |
554 if (decorationStyle->visibility() == HIDDEN) | 540 if (decorationStyle->visibility() == HIDDEN) |
555 return; | 541 return; |
556 | 542 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness))); | 594 path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness))); |
609 | 595 |
610 // acquirePaintingResource also modifies state if the scalingFactor is non-i
dentity. | 596 // acquirePaintingResource also modifies state if the scalingFactor is non-i
dentity. |
611 // Above we have saved the state for this case. | 597 // Above we have saved the state for this case. |
612 if (acquirePaintingResource(context, scalingFactor, decorationRenderer, deco
rationStyle)) | 598 if (acquirePaintingResource(context, scalingFactor, decorationRenderer, deco
rationStyle)) |
613 releasePaintingResource(context, &path); | 599 releasePaintingResource(context, &path); |
614 } | 600 } |
615 | 601 |
616 void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
e* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition,
int endPosition) | 602 void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
e* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition,
int endPosition) |
617 { | 603 { |
618 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 604 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
619 ASSERT(textRenderer); | |
620 | 605 |
621 float scalingFactor = textRenderer->scalingFactor(); | 606 float scalingFactor = textRenderer.scalingFactor(); |
622 ASSERT(scalingFactor); | 607 ASSERT(scalingFactor); |
623 | 608 |
624 const Font& scaledFont = textRenderer->scaledFont(); | 609 const Font& scaledFont = textRenderer.scaledFont(); |
625 const ShadowList* shadowList = style->textShadow(); | 610 const ShadowList* shadowList = style->textShadow(); |
626 | 611 |
627 // Text shadows are disabled when printing. http://crbug.com/258321 | 612 // Text shadows are disabled when printing. http://crbug.com/258321 |
628 bool hasShadow = shadowList && !context->printing(); | 613 bool hasShadow = shadowList && !context->printing(); |
629 | 614 |
630 FloatPoint textOrigin(fragment.x, fragment.y); | 615 FloatPoint textOrigin(fragment.x, fragment.y); |
631 FloatSize textSize(fragment.width, fragment.height); | 616 FloatSize textSize(fragment.width, fragment.height); |
632 | 617 |
633 if (scalingFactor != 1) { | 618 if (scalingFactor != 1) { |
634 textOrigin.scale(scalingFactor, scalingFactor); | 619 textOrigin.scale(scalingFactor, scalingFactor); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 paintTextWithShadows(context, style, textRun, fragment, 0, fragment.leng
th); | 667 paintTextWithShadows(context, style, textRun, fragment, 0, fragment.leng
th); |
683 return; | 668 return; |
684 } | 669 } |
685 | 670 |
686 // Eventually draw text using regular style until the start position of the
selection | 671 // Eventually draw text using regular style until the start position of the
selection |
687 if (startPosition > 0 && !paintSelectedTextOnly) | 672 if (startPosition > 0 && !paintSelectedTextOnly) |
688 paintTextWithShadows(context, style, textRun, fragment, 0, startPosition
); | 673 paintTextWithShadows(context, style, textRun, fragment, 0, startPosition
); |
689 | 674 |
690 // Draw text using selection style from the start to the end position of the
selection | 675 // Draw text using selection style from the start to the end position of the
selection |
691 if (style != selectionStyle) | 676 if (style != selectionStyle) |
692 SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDiffere
nceRepaint, selectionStyle); | 677 SVGResourcesCache::clientStyleChanged(&parent()->renderer(), StyleDiffer
enceRepaint, selectionStyle); |
693 | 678 |
694 TextRun selectionTextRun = constructTextRun(selectionStyle, fragment); | 679 TextRun selectionTextRun = constructTextRun(selectionStyle, fragment); |
695 paintTextWithShadows(context, selectionStyle, textRun, fragment, startPositi
on, endPosition); | 680 paintTextWithShadows(context, selectionStyle, textRun, fragment, startPositi
on, endPosition); |
696 | 681 |
697 if (style != selectionStyle) | 682 if (style != selectionStyle) |
698 SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDiffere
nceRepaint, style); | 683 SVGResourcesCache::clientStyleChanged(&parent()->renderer(), StyleDiffer
enceRepaint, style); |
699 | 684 |
700 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part | 685 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part |
701 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) | 686 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) |
702 paintTextWithShadows(context, style, textRun, fragment, endPosition, fra
gment.length); | 687 paintTextWithShadows(context, style, textRun, fragment, endPosition, fra
gment.length); |
703 } | 688 } |
704 | 689 |
705 void SVGInlineTextBox::paintDocumentMarker(GraphicsContext*, const FloatPoint&,
DocumentMarker*, RenderStyle*, const Font&, bool) | 690 void SVGInlineTextBox::paintDocumentMarker(GraphicsContext*, const FloatPoint&,
DocumentMarker*, RenderStyle*, const Font&, bool) |
706 { | 691 { |
707 // SVG does not have support for generic document markers (e.g., spellchecki
ng, etc). | 692 // SVG does not have support for generic document markers (e.g., spellchecki
ng, etc). |
708 } | 693 } |
709 | 694 |
710 void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const Floa
tPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font) | 695 void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const Floa
tPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font) |
711 { | 696 { |
712 // SVG is only interested in the TextMatch markers. | 697 // SVG is only interested in the TextMatch markers. |
713 if (marker->type() != DocumentMarker::TextMatch) | 698 if (marker->type() != DocumentMarker::TextMatch) |
714 return; | 699 return; |
715 | 700 |
716 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 701 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
717 ASSERT(textRenderer); | |
718 | 702 |
719 FloatRect markerRect; | 703 FloatRect markerRect; |
720 AffineTransform fragmentTransform; | 704 AffineTransform fragmentTransform; |
721 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->next
TextBox()) { | 705 for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextT
extBox()) { |
722 if (!box->isSVGInlineTextBox()) | 706 if (!box->isSVGInlineTextBox()) |
723 continue; | 707 continue; |
724 | 708 |
725 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); | 709 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); |
726 | 710 |
727 int markerStartPosition = max<int>(marker->startOffset() - textBox->star
t(), 0); | 711 int markerStartPosition = max<int>(marker->startOffset() - textBox->star
t(), 0); |
728 int markerEndPosition = min<int>(marker->endOffset() - textBox->start(),
textBox->len()); | 712 int markerEndPosition = min<int>(marker->endOffset() - textBox->start(),
textBox->len()); |
729 | 713 |
730 if (markerStartPosition >= markerEndPosition) | 714 if (markerStartPosition >= markerEndPosition) |
731 continue; | 715 continue; |
732 | 716 |
733 const Vector<SVGTextFragment>& fragments = textBox->textFragments(); | 717 const Vector<SVGTextFragment>& fragments = textBox->textFragments(); |
734 unsigned textFragmentsSize = fragments.size(); | 718 unsigned textFragmentsSize = fragments.size(); |
735 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 719 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
736 const SVGTextFragment& fragment = fragments.at(i); | 720 const SVGTextFragment& fragment = fragments.at(i); |
737 | 721 |
738 int fragmentStartPosition = markerStartPosition; | 722 int fragmentStartPosition = markerStartPosition; |
739 int fragmentEndPosition = markerEndPosition; | 723 int fragmentEndPosition = markerEndPosition; |
740 if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment,
fragmentStartPosition, fragmentEndPosition)) | 724 if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment,
fragmentStartPosition, fragmentEndPosition)) |
741 continue; | 725 continue; |
742 | 726 |
743 FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragm
ent, fragmentStartPosition, fragmentEndPosition, style); | 727 FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragm
ent, fragmentStartPosition, fragmentEndPosition, style); |
744 fragment.buildFragmentTransform(fragmentTransform); | 728 fragment.buildFragmentTransform(fragmentTransform); |
745 | 729 |
746 // Draw the marker highlight. | 730 // Draw the marker highlight. |
747 if (renderer()->frame()->editor().markedTextMatchesAreHighlighted())
{ | 731 if (renderer().frame()->editor().markedTextMatchesAreHighlighted())
{ |
748 Color color = marker->activeMatch() ? | 732 Color color = marker->activeMatch() ? |
749 RenderTheme::theme().platformActiveTextSearchHighlightColor(
) : | 733 RenderTheme::theme().platformActiveTextSearchHighlightColor(
) : |
750 RenderTheme::theme().platformInactiveTextSearchHighlightColo
r(); | 734 RenderTheme::theme().platformInactiveTextSearchHighlightColo
r(); |
751 GraphicsContextStateSaver stateSaver(*context); | 735 GraphicsContextStateSaver stateSaver(*context); |
752 if (!fragmentTransform.isIdentity()) | 736 if (!fragmentTransform.isIdentity()) |
753 context->concatCTM(fragmentTransform); | 737 context->concatCTM(fragmentTransform); |
754 context->setFillColor(color); | 738 context->setFillColor(color); |
755 context->fillRect(fragmentRect, color); | 739 context->fillRect(fragmentRect, color); |
756 } | 740 } |
757 | 741 |
758 fragmentRect = fragmentTransform.mapRect(fragmentRect); | 742 fragmentRect = fragmentTransform.mapRect(fragmentRect); |
759 markerRect.unite(fragmentRect); | 743 markerRect.unite(fragmentRect); |
760 } | 744 } |
761 } | 745 } |
762 | 746 |
763 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsol
uteQuad(markerRect).enclosingBoundingBox()); | 747 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsolu
teQuad(markerRect).enclosingBoundingBox()); |
764 } | 748 } |
765 | 749 |
766 FloatRect SVGInlineTextBox::calculateBoundaries() const | 750 FloatRect SVGInlineTextBox::calculateBoundaries() const |
767 { | 751 { |
768 FloatRect textRect; | 752 FloatRect textRect; |
769 | 753 |
770 RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 754 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); |
771 ASSERT(textRenderer); | |
772 | 755 |
773 float scalingFactor = textRenderer->scalingFactor(); | 756 float scalingFactor = textRenderer.scalingFactor(); |
774 ASSERT(scalingFactor); | 757 ASSERT(scalingFactor); |
775 | 758 |
776 float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / sc
alingFactor; | 759 float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / sca
lingFactor; |
777 | 760 |
778 AffineTransform fragmentTransform; | 761 AffineTransform fragmentTransform; |
779 unsigned textFragmentsSize = m_textFragments.size(); | 762 unsigned textFragmentsSize = m_textFragments.size(); |
780 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 763 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
781 const SVGTextFragment& fragment = m_textFragments.at(i); | 764 const SVGTextFragment& fragment = m_textFragments.at(i); |
782 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width
, fragment.height); | 765 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width
, fragment.height); |
783 fragment.buildFragmentTransform(fragmentTransform); | 766 fragment.buildFragmentTransform(fragmentTransform); |
784 fragmentRect = fragmentTransform.mapRect(fragmentRect); | 767 fragmentRect = fragmentTransform.mapRect(fragmentRect); |
785 | 768 |
786 textRect.unite(fragmentRect); | 769 textRect.unite(fragmentRect); |
787 } | 770 } |
788 | 771 |
789 return textRect; | 772 return textRect; |
790 } | 773 } |
791 | 774 |
792 bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumula
tedOffset, LayoutUnit, LayoutUnit) | 775 bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumula
tedOffset, LayoutUnit, LayoutUnit) |
793 { | 776 { |
794 // FIXME: integrate with InlineTextBox::nodeAtPoint better. | 777 // FIXME: integrate with InlineTextBox::nodeAtPoint better. |
795 ASSERT(!isLineBreak()); | 778 ASSERT(!isLineBreak()); |
796 | 779 |
797 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, r
equest, renderer()->style()->pointerEvents()); | 780 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, r
equest, renderer().style()->pointerEvents()); |
798 bool isVisible = renderer()->style()->visibility() == VISIBLE; | 781 bool isVisible = renderer().style()->visibility() == VISIBLE; |
799 if (isVisible || !hitRules.requireVisible) { | 782 if (isVisible || !hitRules.requireVisible) { |
800 if (hitRules.canHitBoundingBox | 783 if (hitRules.canHitBoundingBox |
801 || (hitRules.canHitStroke && (renderer()->style()->svgStyle()->hasSt
roke() || !hitRules.requireStroke)) | 784 || (hitRules.canHitStroke && (renderer().style()->svgStyle()->hasStr
oke() || !hitRules.requireStroke)) |
802 || (hitRules.canHitFill && (renderer()->style()->svgStyle()->hasFill
() || !hitRules.requireFill))) { | 785 || (hitRules.canHitFill && (renderer().style()->svgStyle()->hasFill(
) || !hitRules.requireFill))) { |
803 FloatPoint boxOrigin(x(), y()); | 786 FloatPoint boxOrigin(x(), y()); |
804 boxOrigin.moveBy(accumulatedOffset); | 787 boxOrigin.moveBy(accumulatedOffset); |
805 FloatRect rect(boxOrigin, size()); | 788 FloatRect rect(boxOrigin, size()); |
806 if (locationInContainer.intersects(rect)) { | 789 if (locationInContainer.intersects(rect)) { |
807 renderer()->updateHitTestResult(result, locationInContainer.poin
t() - toLayoutSize(accumulatedOffset)); | 790 renderer().updateHitTestResult(result, locationInContainer.point
() - toLayoutSize(accumulatedOffset)); |
808 if (!result.addNodeToRectBasedTestResult(renderer()->node(), req
uest, locationInContainer, rect)) | 791 if (!result.addNodeToRectBasedTestResult(renderer().node(), requ
est, locationInContainer, rect)) |
809 return true; | 792 return true; |
810 } | 793 } |
811 } | 794 } |
812 } | 795 } |
813 return false; | 796 return false; |
814 } | 797 } |
815 | 798 |
816 } // namespace WebCore | 799 } // namespace WebCore |
OLD | NEW |