static FloatRect toNormalizedRect(const FloatRect& absoluteRect, const LayoutObject* layoutObject, const LayoutBlock* container) { ASSERT(layoutObject); ASSERT(container || layoutObject->isLayoutView()); if (!container) return FloatRect(); // We want to normalize by the max layout overflow size instead of only the visible bounding box. // Quads and their enclosing bounding boxes need to be used in order to keep results transform-friendly. FloatPoint scrolledOrigin; // For overflow:scroll we need to get where the actual origin is independently of the scroll. if (container->hasOverflowClip()) scrolledOrigin = -IntPoint(container->scrolledContentOffset()); FloatRect overflowRect(scrolledOrigin, FloatSize(container->maxLayoutOverflow())); FloatRect containerRect = container->localToAbsoluteQuad(FloatQuad(overflowRect)).enclosingBoundingBox(); if (containerRect.isEmpty()) return FloatRect(); // Make the coordinates relative to the container enclosing bounding box. // Since we work with rects enclosing quad unions this is still transform-friendly. FloatRect normalizedRect = absoluteRect; normalizedRect.moveBy(-containerRect.location()); // Fixed positions do not make sense in this coordinate system, but need to leave consistent tickmarks. // So, use their position when the view is not scrolled, like an absolute position. if (layoutObject->style()->position() == FixedPosition && container->isLayoutView()) normalizedRect.moveBy(-toLayoutView(container)->frameView()->scrollPosition()); normalizedRect.scale(1 / containerRect.width(), 1 / containerRect.height()); return normalizedRect; }
FloatRect VisualViewport::viewportToRootFrame(const FloatRect& rectInViewport) const { FloatRect rectInRootFrame = rectInViewport; rectInRootFrame.scale(1 / scale()); rectInRootFrame.moveBy(location()); return rectInRootFrame; }
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, 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)); path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); return true; }
FloatRect findInPageRectFromAbsoluteRect(const FloatRect& inputRect, const LayoutObject* baseLayoutObject) { if (!baseLayoutObject || inputRect.isEmpty()) return FloatRect(); // Normalize the input rect to its container block. const LayoutBlock* baseContainer = enclosingScrollableAncestor(baseLayoutObject); FloatRect normalizedRect = toNormalizedRect(inputRect, baseLayoutObject, baseContainer); // Go up across frames. for (const LayoutBox* layoutObject = baseContainer; layoutObject; ) { // Go up the layout tree until we reach the root of the current frame (the LayoutView). while (!layoutObject->isLayoutView()) { const LayoutBlock* container = enclosingScrollableAncestor(layoutObject); // Compose the normalized rects. FloatRect normalizedBoxRect = toNormalizedRect(layoutObject->absoluteBoundingBoxRect(), layoutObject, container); normalizedRect.scale(normalizedBoxRect.width(), normalizedBoxRect.height()); normalizedRect.moveBy(normalizedBoxRect.location()); layoutObject = container; } ASSERT(layoutObject->isLayoutView()); // Jump to the layoutObject owning the frame, if any. layoutObject = layoutObject->frame() ? layoutObject->frame()->ownerLayoutObject() : 0; } return normalizedRect; }
FloatRect VisualViewport::rootFrameToViewport(const FloatRect& rectInRootFrame) const { FloatRect rectInViewport = rectInRootFrame; rectInViewport.moveBy(-location()); rectInViewport.scale(scale()); return rectInViewport; }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, FontCascade& font, TextRun& run, float& textWidth) const { bool includesArrow = shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason); contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontCascadeDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); fontDescription.setRenderingMode(frame().settings().fontRenderingMode()); fontDescription.setComputedSize(12); font = FontCascade(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; }
FloatRect findInPageRectFromAbsoluteRect(const FloatRect& inputRect, const RenderObject* baseRenderer) { if (!baseRenderer || inputRect.isEmpty()) return FloatRect(); // Normalize the input rect to its container block. const RenderBlock* baseContainer = enclosingScrollableAncestor(baseRenderer); FloatRect normalizedRect = toNormalizedRect(inputRect, baseRenderer, baseContainer); // Go up across frames. for (const RenderBox* renderer = baseContainer; renderer; ) { // Go up the render tree until we reach the root of the current frame (the RenderView). while (!renderer->isRenderView()) { const RenderBlock* container = enclosingScrollableAncestor(renderer); // Compose the normalized rects. FloatRect normalizedBoxRect = toNormalizedRect(renderer->absoluteBoundingBoxRect(), renderer, container); normalizedRect.scale(normalizedBoxRect.width(), normalizedBoxRect.height()); normalizedRect.moveBy(normalizedBoxRect.location()); renderer = container; } ASSERT(renderer->isRenderView()); // Jump to the renderer owning the frame, if any. renderer = renderer->frame() ? renderer->frame()->ownerRenderer() : 0; } return normalizedRect; }
FloatRect VisualViewport::mainViewToViewportCSSPixels(const FloatRect& rect) const { // Note, this is in CSS Pixels so we don't apply scale. FloatRect rectInViewport = rect; rectInViewport.moveBy(-location()); return rectInViewport; }
FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward) { FloatRect result = rect; result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize); result.expand(m_kernelSize); return result; }
FloatRect FEConvolveMatrix::mapEffect(const FloatRect& rect) const { if (!parametersValid()) return rect; FloatRect result = rect; result.moveBy(-m_targetOffset); result.expand(FloatSize(m_kernelSize)); return result; }
FloatRect FEDropShadow::mapEffect(const FloatSize& stdDeviation, const FloatPoint& offset, const FloatRect& rect) { FloatRect offsetRect = rect; offsetRect.moveBy(offset); FloatRect blurredRect = FEGaussianBlur::mapEffect(stdDeviation, offsetRect); return unionRect(blurredRect, rect); }
bool AnimationBase::computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle& style, LayoutRect& bounds) const { FloatRect floatBounds = bounds; FloatPoint transformOrigin; bool applyTransformOrigin = containsRotation(style.transform().operations()) || style.transform().affectedByTransformOrigin(); if (applyTransformOrigin) { float offsetX = style.transformOriginX().isPercent() ? rendererBox.x() : 0; float offsetY = style.transformOriginY().isPercent() ? rendererBox.y() : 0; transformOrigin.setX(floatValueForLength(style.transformOriginX(), rendererBox.width()) + offsetX); transformOrigin.setY(floatValueForLength(style.transformOriginY(), rendererBox.height()) + offsetY); // Ignore transformOriginZ because we'll bail if we encounter any 3D transforms. floatBounds.moveBy(-transformOrigin); } for (const auto& operation : style.transform().operations()) { if (operation->type() == TransformOperation::ROTATE) { // For now, just treat this as a full rotation. This could take angle into account to reduce inflation. floatBounds = boundsOfRotatingRect(floatBounds); } else { TransformationMatrix transform; operation->apply(transform, rendererBox.size()); if (!transform.isAffine()) return false; if (operation->type() == TransformOperation::MATRIX || operation->type() == TransformOperation::MATRIX_3D) { TransformationMatrix::Decomposed2Type toDecomp; transform.decompose2(toDecomp); // Any rotation prevents us from using a simple start/end rect union. if (toDecomp.angle) return false; } floatBounds = transform.mapRect(floatBounds); } } if (applyTransformOrigin) floatBounds.moveBy(transformOrigin); bounds = LayoutRect(floatBounds); return true; }
FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward) { FloatRect result = rect; if (parametersValid()) { result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize); result.expand(FloatSize(m_kernelSize)); } return result; }
FloatRect PinchViewport::visibleRectInDocument() const { if (!mainFrame() || !mainFrame()->view()) return FloatRect(); FloatRect viewRect = mainFrame()->view()->visibleContentRect(); FloatRect pinchRect = visibleRect(); pinchRect.moveBy(viewRect.location()); return pinchRect; }
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; }
FloatRect findInPageRectFromAbsoluteRect(const FloatRect& inputRect, const RenderObject* renderer) { if (!renderer || inputRect.isEmpty()) return FloatRect(); // Normalize the input rect to its container, saving the container bounding box for the incoming loop. FloatRect rendererBoundingBox; FloatRect normalizedRect = toNormalizedRect(inputRect, renderer, rendererBoundingBox); renderer = renderer->container(); // Go up across frames. while (renderer) { // Go up the render tree until we reach the root of the current frame (the RenderView). for (const RenderObject* container = renderer->container(); container; renderer = container, container = container->container()) { // Compose the normalized rects. The absolute bounding box of the container is calculated in toNormalizedRect // and can be reused for the next iteration of the loop. FloatRect normalizedBoxRect = toNormalizedRect(rendererBoundingBox, renderer, rendererBoundingBox); normalizedRect.scale(normalizedBoxRect.width(), normalizedBoxRect.height()); normalizedRect.moveBy(normalizedBoxRect.location()); if (normalizedRect.isEmpty()) return normalizedRect; } // Jump to the renderer owning the frame, if any. ASSERT(renderer->isRenderView()); renderer = renderer->frame() ? renderer->frame()->ownerRenderer() : 0; // Update the absolute coordinates to the new frame. if (renderer) rendererBoundingBox = renderer->absoluteBoundingBoxRect(); } return normalizedRect; }
void TileGrid::setTileNeedsDisplayInRect(const TileIndex& tileIndex, TileInfo& tileInfo, const IntRect& repaintRectInTileCoords, const IntRect& coverageRectInTileCoords) { PlatformCALayer* tileLayer = tileInfo.layer.get(); IntRect tileRect = rectForTileIndex(tileIndex); FloatRect tileRepaintRect = tileRect; tileRepaintRect.intersect(repaintRectInTileCoords); if (tileRepaintRect.isEmpty()) return; tileRepaintRect.moveBy(-tileRect.location()); // We could test for intersection with the visible rect. This would reduce painting yet more, // but may make scrolling stale tiles into view more frequent. if (tileRect.intersects(coverageRectInTileCoords) && tileLayer->superlayer()) { tileLayer->setNeedsDisplayInRect(tileRepaintRect); if (m_controller.rootLayer().owner()->platformCALayerShowRepaintCounter(0)) { FloatRect indicatorRect(0, 0, 52, 27); tileLayer->setNeedsDisplayInRect(indicatorRect); } } else tileInfo.hasStaleContent = 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; }