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 "SVGInlineFlowBox.h" 25 26 #if ENABLE(SVG) 27 #include "DocumentMarkerController.h" 28 #include "GraphicsContext.h" 29 #include "RenderSVGInlineText.h" 30 #include "SVGInlineTextBox.h" 31 #include "SVGRenderSupport.h" 32 33 using namespace std; 34 35 namespace WebCore { 36 37 void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo) 38 { 39 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); 40 ASSERT(!paintInfo.context->paintingDisabled()); 41 42 PaintInfo childPaintInfo(paintInfo); 43 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { 44 if (child->isSVGInlineTextBox()) 45 static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo); 46 else if (child->isSVGInlineFlowBox()) 47 static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo); 48 } 49 } 50 51 void SVGInlineFlowBox::paint(PaintInfo& paintInfo, int, int, int, int) 52 { 53 ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); 54 ASSERT(!paintInfo.context->paintingDisabled()); 55 56 RenderObject* boxRenderer = renderer(); 57 ASSERT(boxRenderer); 58 59 PaintInfo childPaintInfo(paintInfo); 60 childPaintInfo.context->save(); 61 62 if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo)) { 63 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { 64 if (child->isSVGInlineTextBox()) 65 computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer())); 66 67 child->paint(childPaintInfo, 0, 0, 0, 0); 68 } 69 } 70 71 SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, paintInfo.context); 72 childPaintInfo.context->restore(); 73 } 74 75 IntRect SVGInlineFlowBox::calculateBoundaries() const 76 { 77 IntRect childRect; 78 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) 79 childRect.unite(child->calculateBoundaries()); 80 return childRect; 81 } 82 83 void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer) 84 { 85 ASSERT(textRenderer); 86 87 Node* node = textRenderer->node(); 88 if (!node || !node->inDocument()) 89 return; 90 91 RenderStyle* style = textRenderer->style(); 92 ASSERT(style); 93 94 AffineTransform fragmentTransform; 95 Document* document = textRenderer->document(); 96 Vector<DocumentMarker> markers = document->markers()->markersForNode(textRenderer->node()); 97 98 Vector<DocumentMarker>::iterator markerEnd = markers.end(); 99 for (Vector<DocumentMarker>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) { 100 const DocumentMarker& marker = *markerIt; 101 102 // SVG is only interessted in the TextMatch marker, for now. 103 if (marker.type != DocumentMarker::TextMatch) 104 continue; 105 106 FloatRect markerRect; 107 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { 108 if (!box->isSVGInlineTextBox()) 109 continue; 110 111 SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); 112 113 int markerStartPosition = max<int>(marker.startOffset - textBox->start(), 0); 114 int markerEndPosition = min<int>(marker.endOffset - textBox->start(), textBox->len()); 115 116 if (markerStartPosition >= markerEndPosition) 117 continue; 118 119 int fragmentStartPosition = 0; 120 int fragmentEndPosition = 0; 121 122 const Vector<SVGTextFragment>& fragments = textBox->textFragments(); 123 unsigned textFragmentsSize = fragments.size(); 124 for (unsigned i = 0; i < textFragmentsSize; ++i) { 125 const SVGTextFragment& fragment = fragments.at(i); 126 127 fragmentStartPosition = markerStartPosition; 128 fragmentEndPosition = markerEndPosition; 129 if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) 130 continue; 131 132 FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style); 133 fragment.buildFragmentTransform(fragmentTransform); 134 if (!fragmentTransform.isIdentity()) 135 fragmentRect = fragmentTransform.mapRect(fragmentRect); 136 137 markerRect.unite(fragmentRect); 138 } 139 } 140 141 document->markers()->setRenderedRectForMarker(node, marker, textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); 142 } 143 } 144 145 } // namespace WebCore 146 147 #endif // ENABLE(SVG) 148