Home | History | Annotate | Download | only in svg
      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