LayoutRect::LayoutRect(const FloatRect& r) : m_location(LayoutPoint(r.location())) , m_size(LayoutSize(r.size())) { }
static bool initializeIndicator(TextIndicatorData& data, Frame& frame, const Range& range, FloatSize margin, bool indicatesCurrentSelection) { Vector<FloatRect> textRects; // FIXME (138888): Ideally we wouldn't remove the margin in this case, but we need to // ensure that the indicator and indicator-with-highlight overlap precisely, and // we can't add a margin to the indicator-with-highlight. if (indicatesCurrentSelection && !(data.options & TextIndicatorOptionIncludeMarginIfRangeMatchesSelection)) margin = FloatSize(); FrameSelection::TextRectangleHeight textRectHeight = (data.options & TextIndicatorOptionTightlyFitContent) ? FrameSelection::TextRectangleHeight::TextHeight : FrameSelection::TextRectangleHeight::SelectionHeight; if ((data.options & TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges) && hasNonInlineOrReplacedElements(range)) data.options |= TextIndicatorOptionPaintAllContent; else { if (data.options & TextIndicatorOptionDoNotClipToVisibleRect) frame.selection().getTextRectangles(textRects, textRectHeight); else frame.selection().getClippedVisibleTextRectangles(textRects, textRectHeight); } if (textRects.isEmpty()) { RenderView* renderView = frame.contentRenderer(); if (!renderView) return false; FloatRect boundingRect = range.absoluteBoundingRect(); if (data.options & TextIndicatorOptionDoNotClipToVisibleRect) textRects.append(boundingRect); else { // Clip to the visible rect, just like getClippedVisibleTextRectangles does. // FIXME: We really want to clip to the unobscured rect in both cases, I think. // (this seems to work on Mac, but maybe not iOS?) FloatRect visibleContentRect = frame.view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect); textRects.append(intersection(visibleContentRect, boundingRect)); } } FloatRect textBoundingRectInRootViewCoordinates; FloatRect textBoundingRectInDocumentCoordinates; Vector<FloatRect> textRectsInRootViewCoordinates; for (const FloatRect& textRect : textRects) { FloatRect textRectInDocumentCoordinatesIncludingMargin = textRect; textRectInDocumentCoordinatesIncludingMargin.inflateX(margin.width()); textRectInDocumentCoordinatesIncludingMargin.inflateY(margin.height()); textBoundingRectInDocumentCoordinates.unite(textRectInDocumentCoordinatesIncludingMargin); FloatRect textRectInRootViewCoordinates = frame.view()->contentsToRootView(enclosingIntRect(textRectInDocumentCoordinatesIncludingMargin)); textRectsInRootViewCoordinates.append(textRectInRootViewCoordinates); textBoundingRectInRootViewCoordinates.unite(textRectInRootViewCoordinates); } Vector<FloatRect> textRectsInBoundingRectCoordinates; for (auto rect : textRectsInRootViewCoordinates) { rect.moveBy(-textBoundingRectInRootViewCoordinates.location()); textRectsInBoundingRectCoordinates.append(rect); } // Store the selection rect in window coordinates, to be used subsequently // to determine if the indicator and selection still precisely overlap. data.selectionRectInRootViewCoordinates = frame.view()->contentsToRootView(enclosingIntRect(frame.selection().selectionBounds())); data.textBoundingRectInRootViewCoordinates = textBoundingRectInRootViewCoordinates; data.textRectsInBoundingRectCoordinates = textRectsInBoundingRectCoordinates; return takeSnapshots(data, frame, enclosingIntRect(textBoundingRectInDocumentCoordinates), textRects); }
bool RenderEmbeddedObject::getReplacementTextGeometry(int tx, int ty, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) { contentRect = contentBoxRect(); contentRect.move(tx, ty); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document()->settings(); ASSERT(settings); if (!settings) return false; fontDescription.setRenderingMode(settings->fontRenderingMode()); fontDescription.setComputedSize(fontDescription.specifiedSize()); font = Font(fontDescription, 0, 0); font.update(0); run = TextRun(m_replacementText.characters(), m_replacementText.length()); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); return true; }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) const { contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontDescription fontDescription; RenderTheme::theme().systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document().settings(); ASSERT(settings); if (!settings) return false; fontDescription.setComputedSize(fontDescription.specifiedSize()); font = Font(fontDescription); font.update(nullptr); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); return true; }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, FloatRect& arrowRect, Font& font, TextRun& run, float& textWidth) const { contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document()->settings(); ASSERT(settings); if (!settings) return false; fontDescription.setRenderingMode(settings->fontRenderingMode()); fontDescription.setComputedSize(fontDescription.specifiedSize()); font = Font(fontDescription, 0, 0); font.update(0); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); replacementTextRect.setHeight(replacementTextRect.height() + replacementTextRoundedRectBottomTextPadding); path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); if (shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason)) { arrowRect = path.boundingRect(); arrowRect.setX(ceilf(arrowRect.maxX() + replacementArrowLeftMargin)); arrowRect.setWidth(arrowRect.height()); arrowRect.inflate(-0.5); path.addEllipse(arrowRect); addReplacementArrowPath(path, arrowRect); } return true; }
IntRect roundedIntRect(const FloatRect& rect) { return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size())); }
IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const { return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size())); }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, Font& font, TextRun& run, float& textWidth) const { bool includesArrow = shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason); contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); fontDescription.setRenderingMode(frame().settings().fontRenderingMode()); fontDescription.setComputedSize(12); font = Font(fontDescription, 0, 0); font.update(0); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftTextMargin + (includesArrow ? replacementTextRoundedRectRightTextMarginWithArrow : replacementTextRoundedRectRightTextMargin), replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); indicatorRect = replacementTextRect; // Expand the background rect to include the arrow, if it will be used. if (includesArrow) { arrowRect = indicatorRect; arrowRect.setX(ceilf(arrowRect.maxX() + replacementArrowLeftMargin)); arrowRect.setWidth(arrowRect.height()); indicatorRect.unite(arrowRect); } return true; }
bool LinkHighlight::computeHighlightLayerPathAndPosition(RenderLayer* compositingLayer) { if (!m_node || !m_node->renderer()) return false; ASSERT(compositingLayer); // Get quads for node in absolute coordinates. Vector<FloatQuad> quads; m_node->renderer()->absoluteQuads(quads); ASSERT(quads.size()); FloatRect positionAdjust; if (!m_usingNonCompositedContentHost) { const RenderStyle* style = m_node->renderer()->style(); // If we have a box shadow, and are non-relative, then must manually adjust // for its size. if (const ShadowData* shadow = style->boxShadow()) { int outlineSize = m_node->renderer()->outlineStyleForRepaint()->outlineSize(); shadow->adjustRectForShadow(positionAdjust, outlineSize); } // If absolute or fixed, need to subtract out our fixed positioning. // FIXME: should we use RenderLayer::staticBlockPosition() here instead? // Perhaps consider this if out-of-flow elements cause further problems. if (m_node->renderer()->isOutOfFlowPositioned()) { FloatPoint delta(style->left().getFloatValue(), style->top().getFloatValue()); positionAdjust.moveBy(delta); } } Path newPath; for (unsigned quadIndex = 0; quadIndex < quads.size(); ++quadIndex) { FloatQuad localQuad = m_node->renderer()->absoluteToLocalQuad(quads[quadIndex], UseTransforms); localQuad.move(-positionAdjust.location().x(), -positionAdjust.location().y()); FloatQuad absoluteQuad = m_node->renderer()->localToAbsoluteQuad(localQuad, UseTransforms); // Transform node quads in target absolute coords to local coordinates in the compositor layer. FloatQuad transformedQuad; convertTargetSpaceQuadToCompositedLayer(absoluteQuad, m_node->renderer(), compositingLayer->renderer(), transformedQuad); // FIXME: for now, we'll only use rounded paths if we have a single node quad. The reason for this is that // we may sometimes get a chain of adjacent boxes (e.g. for text nodes) which end up looking like sausage // links: these should ideally be merged into a single rect before creating the path, but that's // another CL. if (quads.size() == 1 && transformedQuad.isRectilinear()) { FloatSize rectRoundingRadii(3, 3); newPath.addRoundedRect(transformedQuad.boundingBox(), rectRoundingRadii); } else addQuadToPath(transformedQuad, newPath); } FloatRect boundingRect = newPath.boundingRect(); newPath.translate(-toFloatSize(boundingRect.location())); bool pathHasChanged = !(newPath == m_path); if (pathHasChanged) { m_path = newPath; m_contentLayer->layer()->setBounds(enclosingIntRect(boundingRect).size()); } m_contentLayer->layer()->setPosition(boundingRect.location()); return pathHasChanged; }
FloatRect ImageBuffer::clampedRect(const FloatRect& rect) { return FloatRect(rect.location(), clampedSize(rect.size())); }