void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const FloatPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font) { // SVG is only interested in the TextMatch markers. if (marker->type() != DocumentMarker::TextMatch) return; RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); FloatRect markerRect; AffineTransform fragmentTransform; for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0); int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len()); if (markerStartPosition >= markerEndPosition) continue; const Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); int fragmentStartPosition = markerStartPosition; int fragmentEndPosition = markerEndPosition; if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style); fragment.buildFragmentTransform(fragmentTransform); bool fragmentTransformIsIdentity = fragmentTransform.isIdentity(); // Draw the marker highlight. if (renderer()->frame()->editor().markedTextMatchesAreHighlighted()) { Color color = marker->activeMatch() ? RenderTheme::theme().platformActiveTextSearchHighlightColor() : RenderTheme::theme().platformInactiveTextSearchHighlightColor(); GraphicsContextStateSaver stateSaver(*context); if (!fragmentTransformIsIdentity) context->concatCTM(fragmentTransform); context->setFillColor(color); context->fillRect(fragmentRect, color); } if (!fragmentTransformIsIdentity) fragmentRect = fragmentTransform.mapRect(fragmentRect); markerRect.unite(fragmentRect); } } toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); }
void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer) { ASSERT(textRenderer); Node* node = textRenderer->node(); if (!node || !node->inDocument()) return; RenderStyle* style = textRenderer->style(); ASSERT(style); Document* document = textRenderer->document(); Vector<DocumentMarker> markers = document->markers()->markersForNode(textRenderer->node()); Vector<DocumentMarker>::iterator markerEnd = markers.end(); for (Vector<DocumentMarker>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) { const DocumentMarker& marker = *markerIt; // SVG is only interessted in the TextMatch marker, for now. if (marker.type != DocumentMarker::TextMatch) continue; FloatRect markerRect; for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { ASSERT(box->isSVGInlineTextBox()); SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); int markerStartPosition = max<int>(marker.startOffset - textBox->start(), 0); int markerEndPosition = min<int>(marker.endOffset - textBox->start(), textBox->len()); if (markerStartPosition >= markerEndPosition) continue; int fragmentStartPosition = 0; int fragmentEndPosition = 0; const Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); fragmentStartPosition = markerStartPosition; fragmentEndPosition = markerEndPosition; if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style); if (!fragment.transform.isIdentity()) fragmentRect = fragment.transform.mapRect(fragmentRect); markerRect.unite(fragmentRect); } } document->markers()->setRenderedRectForMarker(node, marker, textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); } }
static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last) { ASSERT(userData); Vector<SVGTextLayoutAttributes*>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes*>*>(userData); // This is a copy of std::reverse(first, last). It additionally assures that the metrics map within the renderers belonging to the InlineBoxes are reordered as well. while (true) { if (first == last || first == --last) return; if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) { InlineBox* temp = *first; *first = *last; *last = temp; ++first; continue; } SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first); SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last); // Reordering is only necessary for BiDi text that is _absolutely_ positioned. if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) { RenderSVGInlineText& firstContext = firstTextBox->renderer(); RenderSVGInlineText& lastContext = lastTextBox->renderer(); SVGTextLayoutAttributes* firstAttributes = 0; SVGTextLayoutAttributes* lastAttributes = 0; findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes); swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start()); } InlineBox* temp = *first; *first = *last; *last = temp; ++first; } }
static inline void dumpTextBoxes(Vector<SVGInlineTextBox*>& boxes) { unsigned boxCount = boxes.size(); fprintf(stderr, "Dumping all text fragments in text sub tree, %i boxes\n", boxCount); for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { SVGInlineTextBox* textBox = boxes.at(boxPosition); Vector<SVGTextFragment>& fragments = textBox->textFragments(); fprintf(stderr, "-> Box %i: Dumping text fragments for SVGInlineTextBox, textBox=%p, textRenderer=%p\n", boxPosition, textBox, textBox->textRenderer()); fprintf(stderr, " textBox properties, start=%i, len=%i, box direction=%i\n", textBox->start(), textBox->len(), textBox->direction()); fprintf(stderr, " textRenderer properties, textLength=%i\n", textBox->textRenderer()->textLength()); const UChar* characters = textBox->textRenderer()->characters(); unsigned fragmentCount = fragments.size(); for (unsigned i = 0; i < fragmentCount; ++i) { SVGTextFragment& fragment = fragments.at(i); String fragmentString(characters + fragment.characterOffset, fragment.length); fprintf(stderr, " -> Fragment %i, x=%lf, y=%lf, width=%lf, height=%lf, characterOffset=%i, length=%i, characters='%s'\n" , i, fragment.x, fragment.y, fragment.width, fragment.height, fragment.characterOffset, fragment.length, fragmentString.utf8().data()); } } }
void SVGInlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* context, const LayoutPoint&, DocumentMarker* marker, const ComputedStyle& style, const Font& font) { // SVG is only interested in the TextMatch markers. if (marker->type() != DocumentMarker::TextMatch) return; LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(m_svgInlineTextBox.layoutObject()); AffineTransform fragmentTransform; for (InlineTextBox* box = textLayoutObject.firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); int markerStartPosition = std::max<int>(marker->startOffset() - textBox->start(), 0); int markerEndPosition = std::min<int>(marker->endOffset() - textBox->start(), textBox->len()); if (markerStartPosition >= markerEndPosition) continue; const Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); int fragmentStartPosition = markerStartPosition; int fragmentEndPosition = markerEndPosition; if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style); fragment.buildFragmentTransform(fragmentTransform); // Draw the marker highlight. if (m_svgInlineTextBox.layoutObject().frame()->editor().markedTextMatchesAreHighlighted()) { Color color = marker->activeMatch() ? LayoutTheme::theme().platformActiveTextSearchHighlightColor() : LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); GraphicsContextStateSaver stateSaver(*context); if (!fragmentTransform.isIdentity()) context->concatCTM(fragmentTransform); context->setFillColor(color); context->fillRect(fragmentRect, color); } } } }