1 /* 2 * Copyright (C) 2006 Oliver Hunt <ojh16 (at) student.canterbury.ac.nz> 3 * Copyright (C) 2006 Apple Computer Inc. 4 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 #include "config.h" 24 #include "core/rendering/svg/SVGInlineFlowBox.h" 25 26 #include "core/dom/DocumentMarkerController.h" 27 #include "core/dom/RenderedDocumentMarker.h" 28 #include "core/rendering/svg/RenderSVGInlineText.h" 29 #include "core/rendering/svg/SVGInlineTextBox.h" 30 #include "core/rendering/svg/SVGRenderingContext.h" 31 32 using namespace std; 33 34 namespace WebCore { 35 36 void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo) 37 { 38 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); 39 ASSERT(!paintInfo.context->paintingDisabled()); 40 41 PaintInfo childPaintInfo(paintInfo); 42 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { 43 if (child->isSVGInlineTextBox()) 44 toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo); 45 else if (child->isSVGInlineFlowBox()) 46 toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo); 47 } 48 } 49 50 void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit) 51 { 52 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); 53 ASSERT(!paintInfo.context->paintingDisabled()); 54 55 RenderObject* boxRenderer = renderer(); 56 ASSERT(boxRenderer); 57 58 SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext); 59 if (renderingContext.isRenderingPrepared()) { 60 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { 61 if (child->isSVGInlineTextBox()) 62 computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer())); 63 64 child->paint(paintInfo, LayoutPoint(), 0, 0); 65 } 66 } 67 } 68 69 FloatRect SVGInlineFlowBox::calculateBoundaries() const 70 { 71 FloatRect childRect; 72 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { 73 if (!child->isSVGInlineTextBox() && !child->isSVGInlineFlowBox()) 74 continue; 75 childRect.unite(child->calculateBoundaries()); 76 } 77 return childRect; 78 } 79 80 void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer) 81 { 82 ASSERT(textRenderer); 83 84 Node* node = textRenderer->node(); 85 if (!node || !node->inDocument()) 86 return; 87 88 RenderStyle* style = textRenderer->style(); 89 ASSERT(style); 90 91 AffineTransform fragmentTransform; 92 Document& document = textRenderer->document(); 93 Vector<DocumentMarker*> markers = document.markers()->markersFor(textRenderer->node()); 94 95 Vector<DocumentMarker*>::iterator markerEnd = markers.end(); 96 for (Vector<DocumentMarker*>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) { 97 DocumentMarker* marker = *markerIt; 98 99 // SVG is only interessted in the TextMatch marker, for now. 100 if (marker->type() != DocumentMarker::TextMatch) 101 continue; 102 103 FloatRect markerRect; 104 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { 105 if (!box->isSVGInlineTextBox()) 106 continue; 107 108 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); 109 110 int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0); 111 int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len()); 112 113 if (markerStartPosition >= markerEndPosition) 114 continue; 115 116 int fragmentStartPosition = 0; 117 int fragmentEndPosition = 0; 118 119 const Vector<SVGTextFragment>& fragments = textBox->textFragments(); 120 unsigned textFragmentsSize = fragments.size(); 121 for (unsigned i = 0; i < textFragmentsSize; ++i) { 122 const SVGTextFragment& fragment = fragments.at(i); 123 124 fragmentStartPosition = markerStartPosition; 125 fragmentEndPosition = markerEndPosition; 126 if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) 127 continue; 128 129 FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style); 130 fragment.buildFragmentTransform(fragmentTransform); 131 if (!fragmentTransform.isIdentity()) 132 fragmentRect = fragmentTransform.mapRect(fragmentRect); 133 134 markerRect.unite(fragmentRect); 135 } 136 } 137 138 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); 139 } 140 } 141 142 } // namespace WebCore 143