FloatRect unionRect(const Vector<FloatRect>& rects) { FloatRect result; size_t count = rects.size(); for (size_t i = 0; i < count; ++i) result.unite(rects[i]); return result; }
const FloatRect LineResolver::Iterator::operator*() const { unsigned currentLine = m_runIterator.lineIndex(); auto it = m_runIterator; FloatRect rect = (*it).rect(); while (it.advance().lineIndex() == currentLine) rect.unite((*it).rect()); return rect; }
static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle) { ShadowBlur& shadow = context->platformContext()->shadowBlur(); if (shadow.type() == ShadowBlur::NoShadow) return; // Calculate the extents of the rendered solid paths. cairo_t* cairoContext = context->platformContext()->cr(); OwnPtr<cairo_path_t> path = adoptPtr(cairo_copy_path(cairoContext)); FloatRect solidFigureExtents; double x0 = 0; double x1 = 0; double y0 = 0; double y1 = 0; if (drawingStyle & Stroke) { cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1); solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0); } if (drawingStyle & Fill) { cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1); FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0); solidFigureExtents.unite(fillExtents); } GraphicsContext* shadowContext = shadow.beginShadowLayer(context, solidFigureExtents); if (!shadowContext) return; cairo_t* cairoShadowContext = shadowContext->platformContext()->cr(); // It's important to copy the context properties to the new shadow // context to preserve things such as the fill rule and stroke width. copyContextProperties(cairoContext, cairoShadowContext); if (drawingStyle & Fill) { cairo_save(cairoShadowContext); cairo_append_path(cairoShadowContext, path.get()); shadowContext->platformContext()->prepareForFilling(context->state(), PlatformContextCairo::NoAdjustment); cairo_fill(cairoShadowContext); cairo_restore(cairoShadowContext); } if (drawingStyle & Stroke) { cairo_append_path(cairoShadowContext, path.get()); shadowContext->platformContext()->prepareForStroking(context->state(), PlatformContextCairo::DoNotPreserveAlpha); cairo_stroke(cairoShadowContext); } // The original path may still be hanging around on the context and endShadowLayer // will take care of properly creating a path to draw the result shadow. We remove the path // temporarily and then restore it. // See: https://bugs.webkit.org/show_bug.cgi?id=108897 cairo_new_path(cairoContext); shadow.endShadowLayer(context); cairo_append_path(cairoContext, path.get()); }
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()); }
// RenderSVGContainer is used for <g> elements which do not themselves have a // width or height, so we union all of our child rects as our repaint rect. FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const { FloatRect repaintRect = computeContainerBoundingBox(this, true); // A filter on this container can paint outside of the union of the child repaint rects repaintRect.unite(filterBoundingBoxForRenderer(this)); return repaintRect; }
FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const { FloatRect repaintRect = m_localBounds; // Filters can paint outside the image content repaintRect.unite(filterBoundingBoxForRenderer(this)); return repaintRect; }
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 drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle) { ShadowBlur& shadow = context->platformContext()->shadowBlur(); if (shadow.type() == ShadowBlur::NoShadow) return; // Calculate the extents of the rendered solid paths. cairo_t* cairoContext = context->platformContext()->cr(); OwnPtr<cairo_path_t> path = adoptPtr(cairo_copy_path(cairoContext)); FloatRect solidFigureExtents; double x0 = 0; double x1 = 0; double y0 = 0; double y1 = 0; if (drawingStyle & Stroke) { cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1); solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0); } if (drawingStyle & Fill) { cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1); FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0); solidFigureExtents.unite(fillExtents); } GraphicsContext* shadowContext = shadow.beginShadowLayer(context, solidFigureExtents); if (!shadowContext) return; cairo_t* cairoShadowContext = shadowContext->platformContext()->cr(); // It's important to copy the context properties to the new shadow // context to preserve things such as the fill rule and stroke width. copyContextProperties(cairoContext, cairoShadowContext); if (drawingStyle & Fill) { cairo_save(cairoShadowContext); cairo_append_path(cairoShadowContext, path.get()); shadowContext->platformContext()->prepareForFilling(context->state(), PlatformContextCairo::NoAdjustment); cairo_clip(cairoShadowContext); cairo_paint(cairoShadowContext); cairo_restore(cairoShadowContext); } if (drawingStyle & Stroke) { cairo_append_path(cairoShadowContext, path.get()); shadowContext->platformContext()->prepareForStroking(context->state(), PlatformContextCairo::DoNotPreserveAlpha); cairo_stroke(cairoShadowContext); } shadow.endShadowLayer(context); // ShadowBlur::endShadowLayer destroys the current path on the Cairo context. We restore it here. cairo_new_path(cairoContext); cairo_append_path(cairoContext, path.get()); }
IntRect RenderPath::absoluteClippedOverflowRect() { FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); // Markers can expand the bounding box repaintRect.unite(m_markerBounds); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter())); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
IntRect RenderSVGContainer::absoluteClippedOverflowRect() { FloatRect repaintRect; for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling()) repaintRect.unite(current->absoluteClippedOverflowRect()); #if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
FloatRect CCRenderSurface::drawableContentRect() const { FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(), m_contentRect.width(), m_contentRect.height()); FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect); if (hasReplica()) drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect)); return drawableContentRect; }
FloatRect RenderSurfaceChromium::drawableContentRect() const { FloatRect localContentRect(-0.5 * m_contentRect.width(), -0.5 * m_contentRect.height(), m_contentRect.width(), m_contentRect.height()); FloatRect drawableContentRect = m_drawTransform.mapRect(localContentRect); if (m_owningLayer->replicaLayer()) drawableContentRect.unite(m_replicaDrawTransform.mapRect(localContentRect)); return drawableContentRect; }
FloatRect SVGInlineFlowBox::calculateBoundaries() const { FloatRect childRect; for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (!child->isSVGInlineTextBox() && !child->isSVGInlineFlowBox()) continue; childRect.unite(child->calculateBoundaries()); } return childRect; }
static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect, const FloatRect& preFilterRect, const WebKit::WebFilterOperations& filters) { FloatRect expandedDamageRect = damageRect; expandRectWithFilters(expandedDamageRect, filters); FloatRect filterRect = preFilterRect; expandRectWithFilters(filterRect, filters); expandedDamageRect.intersect(filterRect); damageRect.unite(expandedDamageRect); }
IntRect RenderPath::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/) { // FIXME: handle non-root repaintContainer FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); // Markers can expand the bounding box repaintRect.unite(m_markerBounds); #if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); #endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect); }
FloatRect FilterEffect::mapRectRecursive(const FloatRect& rect) { FloatRect result; if (m_inputEffects.size() > 0) { result = m_inputEffects.at(0)->mapRectRecursive(rect); for (unsigned i = 1; i < m_inputEffects.size(); ++i) result.unite(m_inputEffects.at(i)->mapRectRecursive(rect)); } else result = rect; return mapRect(result); }
void FEOffset::determineAbsolutePaintRect() { FloatRect paintRect = inputEffect(0)->absolutePaintRect(); Filter& filter = this->filter(); paintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); if (clipsToBounds()) paintRect.intersect(maxEffectRect()); else paintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(paintRect)); }
FloatRect FilterEffect::mapInputs(const FloatRect& rect) const { if (!m_inputEffects.size()) { if (clipsToBounds()) return absoluteBounds(); return rect; } FloatRect inputUnion; for (const auto& effect : m_inputEffects) inputUnion.unite(effect->mapRect(rect)); return inputUnion; }
FloatRect FEMerge::uniteChildEffectSubregions(Filter* filter) { ASSERT(!m_mergeInputs.isEmpty()); FloatRect uniteEffectRect = m_mergeInputs[0]->calculateEffectRect(filter); for (unsigned i = 1; i < m_mergeInputs.size(); i++) uniteEffectRect.unite(m_mergeInputs[i]->calculateEffectRect(filter)); return uniteEffectRect; }
void FEMorphology::determineAbsolutePaintRect() { FloatRect paintRect = inputEffect(0)->absolutePaintRect(); Filter& filter = this->filter(); paintRect.inflateX(filter.applyHorizontalScale(m_radiusX)); paintRect.inflateY(filter.applyVerticalScale(m_radiusY)); if (clipsToBounds()) paintRect.intersect(maxEffectRect()); else paintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(paintRect)); }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const { FloatRect rect; RenderObject* current = firstChild(); for (; current != 0; current = current->nextSibling()) { FloatRect childBBox = current->relativeBBox(includeStroke); FloatRect mappedBBox = current->localTransform().mapRect(childBBox); rect.unite(mappedBBox); } return rect; }
FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const { FloatRect strokeBoundingBox = m_strokeBoundingBox; if (style().svgStyle().hasStroke()) { // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke. float strokeWidth = this->strokeWidth(); for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth)); } return strokeBoundingBox; }
FloatRect SVGRenderBase::computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent) { FloatRect boundingBox; RenderObject* current = container->firstChild(); for (; current != 0; current = current->nextSibling()) { FloatRect childBBox = includeAllPaintedContent ? current->repaintRectInLocalCoordinates() : current->objectBoundingBox(); FloatRect childBBoxInLocalCoords = current->localToParentTransform().mapRect(childBBox); boundingBox.unite(childBBoxInLocalCoords); } return boundingBox; }
void FEDropShadow::determineAbsolutePaintRect() { Filter& filter = this->filter(); FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); FloatRect absoluteOffsetPaintRect(absolutePaintRect); absoluteOffsetPaintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); absolutePaintRect.unite(absoluteOffsetPaintRect); IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY)); // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSize.width() * 0.5f); absolutePaintRect.inflateY(3 * kernelSize.height() * 0.5f); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
void FEDropShadow::determineAbsolutePaintRect() { Filter* filter = this->filter(); ASSERT(filter); FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); FloatRect absoluteOffsetPaintRect(absolutePaintRect); absoluteOffsetPaintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); absolutePaintRect.unite(absoluteOffsetPaintRect); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); unsigned kernelSizeX = 0; unsigned kernelSizeY = 0; FEGaussianBlur::calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY); // We take the half kernel size and multiply it with three, because we run box blur three times. absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f); absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
FloatRect LayoutSVGShape::calculateStrokeBoundingBox() const { ASSERT(m_path); FloatRect strokeBoundingBox = m_fillBoundingBox; if (style()->svgStyle().hasStroke()) { StrokeData strokeData; SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, styleRef(), *this); if (hasNonScalingStroke()) { AffineTransform nonScalingTransform = nonScalingStrokeTransform(); if (nonScalingTransform.isInvertible()) { Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform); FloatRect strokeBoundingRect = usePath->strokeBoundingRect(strokeData); strokeBoundingRect = nonScalingTransform.inverse().mapRect(strokeBoundingRect); strokeBoundingBox.unite(strokeBoundingRect); } } else { strokeBoundingBox.unite(path().strokeBoundingRect(strokeData)); } } return strokeBoundingBox; }
void FEDropShadow::determineAbsolutePaintRect() { Filter* filter = this->filter(); ASSERT(filter); FloatRect absolutePaintRect = mapRect(inputEffect(0)->absolutePaintRect()); if (clipsToBounds()) absolutePaintRect.intersect(maxEffectRect()); else absolutePaintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
FloatRect CCDamageTracker::trackDamageFromLeftoverRects() { // After computing damage for all active layers, any leftover items in the current // rect history correspond to layers/surfaces that no longer exist. So, these regions // are now exposed on the target surface. FloatRect damageRect = FloatRect(); for (RectMap::iterator it = m_currentRectHistory->begin(); it != m_currentRectHistory->end(); ++it) damageRect.unite(it->second); m_currentRectHistory->clear(); return damageRect; }