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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 int SVGInlineTextBox::offsetForPosition(float, bool) const | 79 int SVGInlineTextBox::offsetForPosition(float, bool) const |
80 { | 80 { |
81 // SVG doesn't use the standard offset <-> position selection system, as it'
s not suitable for SVGs complex needs. | 81 // SVG doesn't use the standard offset <-> position selection system, as it'
s not suitable for SVGs complex needs. |
82 // vertical text selection, inline boxes spanning multiple lines (contrary t
o HTML, etc.) | 82 // vertical text selection, inline boxes spanning multiple lines (contrary t
o HTML, etc.) |
83 ASSERT_NOT_REACHED(); | 83 ASSERT_NOT_REACHED(); |
84 return 0; | 84 return 0; |
85 } | 85 } |
86 | 86 |
87 int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
t, float position, bool includePartialGlyphs) const | 87 int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
t, float position, bool includePartialGlyphs) const |
88 { | 88 { |
89 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 89 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
90 | 90 |
91 float scalingFactor = textRenderer.scalingFactor(); | 91 float scalingFactor = textRenderer.scalingFactor(); |
92 ASSERT(scalingFactor); | 92 ASSERT(scalingFactor); |
93 | 93 |
94 RenderStyle* style = textRenderer.style(); | 94 RenderStyle* style = textRenderer.style(); |
95 ASSERT(style); | 95 ASSERT(style); |
96 | 96 |
97 TextRun textRun = constructTextRun(style, fragment); | 97 TextRun textRun = constructTextRun(style, fragment); |
98 | 98 |
99 // Eventually handle lengthAdjust="spacingAndGlyphs". | 99 // Eventually handle lengthAdjust="spacingAndGlyphs". |
(...skipping 13 matching lines...) Expand all Loading... |
113 return 0; | 113 return 0; |
114 } | 114 } |
115 | 115 |
116 FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
fragment, int startPosition, int endPosition, RenderStyle* style) | 116 FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
fragment, int startPosition, int endPosition, RenderStyle* style) |
117 { | 117 { |
118 ASSERT(startPosition < endPosition); | 118 ASSERT(startPosition < endPosition); |
119 ASSERT(style); | 119 ASSERT(style); |
120 | 120 |
121 FontCachePurgePreventer fontCachePurgePreventer; | 121 FontCachePurgePreventer fontCachePurgePreventer; |
122 | 122 |
123 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 123 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
124 | 124 |
125 float scalingFactor = textRenderer.scalingFactor(); | 125 float scalingFactor = textRenderer.scalingFactor(); |
126 ASSERT(scalingFactor); | 126 ASSERT(scalingFactor); |
127 | 127 |
128 const Font& scaledFont = textRenderer.scaledFont(); | 128 const Font& scaledFont = textRenderer.scaledFont(); |
129 const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); | 129 const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); |
130 FloatPoint textOrigin(fragment.x, fragment.y); | 130 FloatPoint textOrigin(fragment.x, fragment.y); |
131 if (scalingFactor != 1) | 131 if (scalingFactor != 1) |
132 textOrigin.scale(scalingFactor, scalingFactor); | 132 textOrigin.scale(scalingFactor, scalingFactor); |
133 | 133 |
134 textOrigin.move(0, -scaledFontMetrics.floatAscent()); | 134 textOrigin.move(0, -scaledFontMetrics.floatAscent()); |
135 | 135 |
136 FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(s
tyle, fragment), textOrigin, fragment.height * scalingFactor, startPosition, end
Position); | 136 FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(s
tyle, fragment), textOrigin, fragment.height * scalingFactor, startPosition, end
Position); |
137 if (scalingFactor == 1) | 137 if (scalingFactor == 1) |
138 return selectionRect; | 138 return selectionRect; |
139 | 139 |
140 selectionRect.scale(1 / scalingFactor); | 140 selectionRect.scale(1 / scalingFactor); |
141 return selectionRect; | 141 return selectionRect; |
142 } | 142 } |
143 | 143 |
144 LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
on) | 144 LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
on) |
145 { | 145 { |
146 int boxStart = start(); | 146 int boxStart = start(); |
147 startPosition = std::max(startPosition - boxStart, 0); | 147 startPosition = std::max(startPosition - boxStart, 0); |
148 endPosition = std::min(endPosition - boxStart, static_cast<int>(len())); | 148 endPosition = std::min(endPosition - boxStart, static_cast<int>(len())); |
149 if (startPosition >= endPosition) | 149 if (startPosition >= endPosition) |
150 return LayoutRect(); | 150 return LayoutRect(); |
151 | 151 |
152 RenderStyle* style = textRenderer().style(); | 152 RenderStyle* style = renderer().style(); |
153 ASSERT(style); | 153 ASSERT(style); |
154 | 154 |
155 AffineTransform fragmentTransform; | 155 AffineTransform fragmentTransform; |
156 FloatRect selectionRect; | 156 FloatRect selectionRect; |
157 int fragmentStartPosition = 0; | 157 int fragmentStartPosition = 0; |
158 int fragmentEndPosition = 0; | 158 int fragmentEndPosition = 0; |
159 | 159 |
160 unsigned textFragmentsSize = m_textFragments.size(); | 160 unsigned textFragmentsSize = m_textFragments.size(); |
161 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 161 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
162 const SVGTextFragment& fragment = m_textFragments.at(i); | 162 const SVGTextFragment& fragment = m_textFragments.at(i); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 // Determine whether or not we're selected. | 198 // Determine whether or not we're selected. |
199 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; | 199 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; |
200 bool hasSelection = selectionState() != RenderObject::SelectionNone; | 200 bool hasSelection = selectionState() != RenderObject::SelectionNone; |
201 if (!hasSelection || paintSelectedTextOnly) | 201 if (!hasSelection || paintSelectedTextOnly) |
202 return; | 202 return; |
203 | 203 |
204 Color backgroundColor = renderer().selectionBackgroundColor(); | 204 Color backgroundColor = renderer().selectionBackgroundColor(); |
205 if (!backgroundColor.alpha()) | 205 if (!backgroundColor.alpha()) |
206 return; | 206 return; |
207 | 207 |
208 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 208 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
209 if (!textShouldBePainted(textRenderer)) | 209 if (!textShouldBePainted(textRenderer)) |
210 return; | 210 return; |
211 | 211 |
212 RenderStyle* style = parentRenderer.style(); | 212 RenderStyle* style = parentRenderer.style(); |
213 ASSERT(style); | 213 ASSERT(style); |
214 | 214 |
215 int startPosition, endPosition; | 215 int startPosition, endPosition; |
216 selectionStartEnd(startPosition, endPosition); | 216 selectionStartEnd(startPosition, endPosition); |
217 | 217 |
218 int fragmentStartPosition = 0; | 218 int fragmentStartPosition = 0; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // Note: We're explicitely not supporting composition & custom underlines an
d custom highlighters - unlike InlineTextBox. | 252 // Note: We're explicitely not supporting composition & custom underlines an
d custom highlighters - unlike InlineTextBox. |
253 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. | 253 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. |
254 | 254 |
255 RenderObject& parentRenderer = parent()->renderer(); | 255 RenderObject& parentRenderer = parent()->renderer(); |
256 | 256 |
257 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; | 257 bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; |
258 bool hasSelection = !parentRenderer.document().printing() && selectionState(
) != RenderObject::SelectionNone; | 258 bool hasSelection = !parentRenderer.document().printing() && selectionState(
) != RenderObject::SelectionNone; |
259 if (!hasSelection && paintSelectedTextOnly) | 259 if (!hasSelection && paintSelectedTextOnly) |
260 return; | 260 return; |
261 | 261 |
262 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 262 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
263 if (!textShouldBePainted(textRenderer)) | 263 if (!textShouldBePainted(textRenderer)) |
264 return; | 264 return; |
265 | 265 |
266 RenderStyle* style = parentRenderer.style(); | 266 RenderStyle* style = parentRenderer.style(); |
267 ASSERT(style); | 267 ASSERT(style); |
268 | 268 |
269 paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.sca
ledFont(), true); | 269 paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.sca
ledFont(), true); |
270 | 270 |
271 const SVGRenderStyle& svgStyle = style->svgStyle(); | 271 const SVGRenderStyle& svgStyle = style->svgStyle(); |
272 | 272 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); | 420 TextRun::RenderingContext* renderingContext = textRun.renderingContext(); |
421 if (renderingContext) | 421 if (renderingContext) |
422 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(0); | 422 static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePai
ntingResource(0); |
423 #endif | 423 #endif |
424 } | 424 } |
425 | 425 |
426 TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
ment& fragment) const | 426 TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
ment& fragment) const |
427 { | 427 { |
428 ASSERT(style); | 428 ASSERT(style); |
429 | 429 |
430 RenderText* text = &textRenderer(); | 430 RenderText* text = &renderer(); |
431 | 431 |
432 // FIXME(crbug.com/264211): This should not be necessary but can occur if we | 432 // FIXME(crbug.com/264211): This should not be necessary but can occur if we |
433 // layout during layout. Remove this when 264211 is
fixed. | 433 // layout during layout. Remove this when 264211 is
fixed. |
434 RELEASE_ASSERT(!text->needsLayout()); | 434 RELEASE_ASSERT(!text->needsLayout()); |
435 | 435 |
436 TextRun run(static_cast<const LChar*>(0) // characters, will be set below if
non-zero. | 436 TextRun run(static_cast<const LChar*>(0) // characters, will be set below if
non-zero. |
437 , 0 // length, will be set below if non-zero. | 437 , 0 // length, will be set below if non-zero. |
438 , 0 // xPos, only relevant with allowTabs=true | 438 , 0 // xPos, only relevant with allowTabs=true |
439 , 0 // padding, only relevant for justified text, not relevant f
or SVG | 439 , 0 // padding, only relevant for justified text, not relevant f
or SVG |
440 , TextRun::AllowTrailingExpansion | 440 , TextRun::AllowTrailingExpansion |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 | 521 |
522 parentBox = parentBox->parent(); | 522 parentBox = parentBox->parent(); |
523 } | 523 } |
524 | 524 |
525 ASSERT(renderer); | 525 ASSERT(renderer); |
526 return renderer; | 526 return renderer; |
527 } | 527 } |
528 | 528 |
529 void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
decoration, const SVGTextFragment& fragment) | 529 void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
decoration, const SVGTextFragment& fragment) |
530 { | 530 { |
531 if (textRenderer().style()->textDecorationsInEffect() == TextDecorationNone) | 531 if (renderer().style()->textDecorationsInEffect() == TextDecorationNone) |
532 return; | 532 return; |
533 | 533 |
534 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. | 534 // 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 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
parent()); | 535 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
parent()); |
536 RenderStyle* decorationStyle = decorationRenderer->style(); | 536 RenderStyle* decorationStyle = decorationRenderer->style(); |
537 ASSERT(decorationStyle); | 537 ASSERT(decorationStyle); |
538 | 538 |
539 if (decorationStyle->visibility() == HIDDEN) | 539 if (decorationStyle->visibility() == HIDDEN) |
540 return; | 540 return; |
541 | 541 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 // acquirePaintingResource also modifies state if the scalingFactor is non-i
dentity. | 599 // acquirePaintingResource also modifies state if the scalingFactor is non-i
dentity. |
600 // Above we have saved the state for this case. | 600 // Above we have saved the state for this case. |
601 if (acquirePaintingResource(context, scalingFactor, decorationRenderer, deco
rationStyle, resourceMode)) | 601 if (acquirePaintingResource(context, scalingFactor, decorationRenderer, deco
rationStyle, resourceMode)) |
602 releasePaintingResource(context, &path, resourceMode); | 602 releasePaintingResource(context, &path, resourceMode); |
603 } | 603 } |
604 | 604 |
605 void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
e* style, | 605 void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
e* style, |
606 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, | 606 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, |
607 RenderSVGResourceModeFlags resourceMode) | 607 RenderSVGResourceModeFlags resourceMode) |
608 { | 608 { |
609 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 609 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
610 | 610 |
611 float scalingFactor = textRenderer.scalingFactor(); | 611 float scalingFactor = textRenderer.scalingFactor(); |
612 ASSERT(scalingFactor); | 612 ASSERT(scalingFactor); |
613 | 613 |
614 const Font& scaledFont = textRenderer.scaledFont(); | 614 const Font& scaledFont = textRenderer.scaledFont(); |
615 const ShadowList* shadowList = style->textShadow(); | 615 const ShadowList* shadowList = style->textShadow(); |
616 | 616 |
617 // Text shadows are disabled when printing. http://crbug.com/258321 | 617 // Text shadows are disabled when printing. http://crbug.com/258321 |
618 bool hasShadow = shadowList && !context->printing(); | 618 bool hasShadow = shadowList && !context->printing(); |
619 | 619 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 { | 694 { |
695 // SVG does not have support for generic document markers (e.g., spellchecki
ng, etc). | 695 // SVG does not have support for generic document markers (e.g., spellchecki
ng, etc). |
696 } | 696 } |
697 | 697 |
698 void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const Floa
tPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font) | 698 void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const Floa
tPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font) |
699 { | 699 { |
700 // SVG is only interested in the TextMatch markers. | 700 // SVG is only interested in the TextMatch markers. |
701 if (marker->type() != DocumentMarker::TextMatch) | 701 if (marker->type() != DocumentMarker::TextMatch) |
702 return; | 702 return; |
703 | 703 |
704 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 704 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
705 | 705 |
706 FloatRect markerRect; | 706 FloatRect markerRect; |
707 AffineTransform fragmentTransform; | 707 AffineTransform fragmentTransform; |
708 for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextT
extBox()) { | 708 for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextT
extBox()) { |
709 if (!box->isSVGInlineTextBox()) | 709 if (!box->isSVGInlineTextBox()) |
710 continue; | 710 continue; |
711 | 711 |
712 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); | 712 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); |
713 | 713 |
714 int markerStartPosition = std::max<int>(marker->startOffset() - textBox-
>start(), 0); | 714 int markerStartPosition = std::max<int>(marker->startOffset() - textBox-
>start(), 0); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 } | 747 } |
748 } | 748 } |
749 | 749 |
750 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsolu
teQuad(markerRect).enclosingBoundingBox()); | 750 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsolu
teQuad(markerRect).enclosingBoundingBox()); |
751 } | 751 } |
752 | 752 |
753 FloatRect SVGInlineTextBox::calculateBoundaries() const | 753 FloatRect SVGInlineTextBox::calculateBoundaries() const |
754 { | 754 { |
755 FloatRect textRect; | 755 FloatRect textRect; |
756 | 756 |
757 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer
()); | 757 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer()); |
758 | 758 |
759 float scalingFactor = textRenderer.scalingFactor(); | 759 float scalingFactor = textRenderer.scalingFactor(); |
760 ASSERT(scalingFactor); | 760 ASSERT(scalingFactor); |
761 | 761 |
762 float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / sca
lingFactor; | 762 float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / sca
lingFactor; |
763 | 763 |
764 AffineTransform fragmentTransform; | 764 AffineTransform fragmentTransform; |
765 unsigned textFragmentsSize = m_textFragments.size(); | 765 unsigned textFragmentsSize = m_textFragments.size(); |
766 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 766 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
767 const SVGTextFragment& fragment = m_textFragments.at(i); | 767 const SVGTextFragment& fragment = m_textFragments.at(i); |
(...skipping 25 matching lines...) Expand all Loading... |
793 renderer().updateHitTestResult(result, locationInContainer.point
() - toLayoutSize(accumulatedOffset)); | 793 renderer().updateHitTestResult(result, locationInContainer.point
() - toLayoutSize(accumulatedOffset)); |
794 if (!result.addNodeToRectBasedTestResult(renderer().node(), requ
est, locationInContainer, rect)) | 794 if (!result.addNodeToRectBasedTestResult(renderer().node(), requ
est, locationInContainer, rect)) |
795 return true; | 795 return true; |
796 } | 796 } |
797 } | 797 } |
798 } | 798 } |
799 return false; | 799 return false; |
800 } | 800 } |
801 | 801 |
802 } // namespace blink | 802 } // namespace blink |
OLD | NEW |