void ScrollableArea::programmaticScrollHelper(const DoublePoint& position, ScrollBehavior scrollBehavior) { cancelScrollAnimation(); if (scrollBehavior == ScrollBehaviorSmooth) programmaticScrollAnimator()->animateToOffset(toFloatPoint(position)); else programmaticScrollAnimator()->scrollToOffsetWithoutAnimation(toFloatPoint(position)); }
void GraphicsLayer::didScroll() { if (m_scrollableArea) { DoublePoint newPosition = m_scrollableArea->minimumScrollPosition() + toDoubleSize(m_layer->layer()->scrollPositionDouble()); // FIXME: Remove the toFloatPoint(). crbug.com/414283. m_scrollableArea->scrollToOffsetWithoutAnimation(toFloatPoint(newPosition)); } }
static bool findLineSegmentIntersection(const FloatPointGraph::Edge& edgeA, const FloatPointGraph::Edge& edgeB, FloatPoint& intersectionPoint) { if (!findIntersection(*edgeA.first, *edgeA.second, *edgeB.first, *edgeB.second, intersectionPoint)) return false; FloatPoint edgeAVec(*edgeA.second - *edgeA.first); FloatPoint edgeBVec(*edgeB.second - *edgeB.first); float dotA = edgeAVec.dot(toFloatPoint(intersectionPoint - *edgeA.first)); if (dotA < 0 || dotA > edgeAVec.lengthSquared()) return false; float dotB = edgeBVec.dot(toFloatPoint(intersectionPoint - *edgeB.first)); if (dotB < 0 || dotB > edgeBVec.lengthSquared()) return false; return true; }
void ScrollableArea::userScrollHelper(const DoublePoint& position, ScrollBehavior scrollBehavior) { cancelProgrammaticScrollAnimation(); // Smooth user scrolls (keyboard, wheel clicks) are handled via the userScroll method. // TODO(bokan): The userScroll method should probably be modified to call this method // and ScrollAnimator to have a simpler animateToOffset method like the // ProgrammaticScrollAnimator. ASSERT(scrollBehavior == ScrollBehaviorInstant); scrollAnimator()->scrollToOffsetWithoutAnimation(toFloatPoint(position)); }
void DrawGlyphs::computeBounds() { // FIXME: This code doesn't actually take the extents of the glyphs into consideration. It assumes that // the glyph lies entirely within its [(ascent + descent), advance] rect. float ascent = m_font->fontMetrics().floatAscent(); float descent = m_font->fontMetrics().floatDescent(); FloatPoint current = toFloatPoint(localAnchor()); size_t numGlyphs = m_glyphs.size(); for (size_t i = 0; i < numGlyphs; ++i) { GlyphBufferAdvance advance = m_advances[i]; FloatRect glyphRect = FloatRect(current.x(), current.y() - ascent, advance.width(), ascent + descent); m_bounds.unite(glyphRect); current.move(advance.width(), advance.height()); } }
void ScrollableArea::scrollPositionChanged(const DoublePoint& position, ScrollType scrollType) { TRACE_EVENT0("blink", "ScrollableArea::scrollPositionChanged"); DoublePoint oldPosition = scrollPositionDouble(); DoublePoint truncatedPosition = shouldUseIntegerScrollOffset() ? flooredIntPoint(position) : position; // Tell the derived class to scroll its contents. setScrollOffset(truncatedPosition, scrollType); Scrollbar* verticalScrollbar = this->verticalScrollbar(); // Tell the scrollbars to update their thumb postions. if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) { horizontalScrollbar->offsetDidChange(); if (horizontalScrollbar->isOverlayScrollbar() && !hasLayerForHorizontalScrollbar()) { if (!verticalScrollbar) horizontalScrollbar->invalidate(); else { // If there is both a horizontalScrollbar and a verticalScrollbar, // then we must also invalidate the corner between them. IntRect boundsAndCorner = horizontalScrollbar->boundsRect(); boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrollbar->width()); horizontalScrollbar->invalidateRect(boundsAndCorner); } } } if (verticalScrollbar) { verticalScrollbar->offsetDidChange(); if (verticalScrollbar->isOverlayScrollbar() && !hasLayerForVerticalScrollbar()) verticalScrollbar->invalidate(); } if (scrollPositionDouble() != oldPosition) { // FIXME: Pass in DoubleSize. crbug.com/414283. scrollAnimator()->notifyContentAreaScrolled(toFloatSize(scrollPositionDouble() - oldPosition)); } scrollAnimator()->setCurrentPosition(toFloatPoint(position)); }
FloatSize ScrollAnimatorBase::computeDeltaToConsume(const FloatSize& delta) const { FloatPoint newPos = toFloatPoint(m_scrollableArea->clampScrollPosition(m_currentPos + delta)); return newPos - m_currentPos; }
void VisualViewport::setScrollOffset(const DoublePoint& offset, ScrollType) { setLocation(toFloatPoint(offset)); }
Path PathUtilities::pathWithShrinkWrappedRects(const Vector<FloatRect>& rects, float radius) { Path path; if (rects.isEmpty()) return path; if (rects.size() > 20) { path.addRoundedRect(unionRect(rects), FloatSize(radius, radius)); return path; } Vector<FloatRect> sortedRects = rects; std::sort(sortedRects.begin(), sortedRects.end(), [](FloatRect a, FloatRect b) { return b.y() > a.y(); }); FloatPointGraph graph; Vector<FloatPointGraph::Polygon> rectPolygons; rectPolygons.reserveInitialCapacity(sortedRects.size()); for (auto& rect : sortedRects) { bool isContained = false; for (auto& otherRect : sortedRects) { if (&rect == &otherRect) continue; if (otherRect.contains(rect)) { isContained = true; break; } } if (!isContained) rectPolygons.append(edgesForRect(rect, graph)); } Vector<FloatPointGraph::Polygon> polys = unitePolygons(rectPolygons, graph); if (polys.isEmpty()) { path.addRoundedRect(unionRect(sortedRects), FloatSize(radius, radius)); return path; } for (auto& poly : polys) { for (unsigned i = 0; i < poly.size(); i++) { FloatPointGraph::Edge& toEdge = poly[i]; // Connect the first edge to the last. FloatPointGraph::Edge& fromEdge = (i > 0) ? poly[i - 1] : poly[poly.size() - 1]; FloatPoint fromEdgeVec = toFloatPoint(*fromEdge.second - *fromEdge.first); FloatPoint toEdgeVec = toFloatPoint(*toEdge.second - *toEdge.first); // Clamp the radius to no more than half the length of either adjacent edge, // because we want a smooth curve and don't want unequal radii. float clampedRadius = std::min(radius, fabsf(fromEdgeVec.x() ? fromEdgeVec.x() : fromEdgeVec.y()) / 2); clampedRadius = std::min(clampedRadius, fabsf(toEdgeVec.x() ? toEdgeVec.x() : toEdgeVec.y()) / 2); FloatPoint fromEdgeNorm = fromEdgeVec; fromEdgeNorm.normalize(); FloatPoint toEdgeNorm = toEdgeVec; toEdgeNorm.normalize(); // Project the radius along the incoming and outgoing edge. FloatSize fromOffset = clampedRadius * toFloatSize(fromEdgeNorm); FloatSize toOffset = clampedRadius * toFloatSize(toEdgeNorm); if (!i) path.moveTo(*fromEdge.second - fromOffset); else path.addLineTo(*fromEdge.second - fromOffset); path.addArcTo(*fromEdge.second, *toEdge.first + toOffset, clampedRadius); } path.closeSubpath(); } return path; }
void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } ASSERT(!isBitmapImage() || notSolidColor()); #if PLATFORM(IOS) FloatSize intrinsicTileSize = originalSize(); #else FloatSize intrinsicTileSize = size(); #endif if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatRect oneTileRect; FloatSize actualTileSize(scaledTileSize.width() + spacing.width(), scaledTileSize.height() + spacing.height()); oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height())); oneTileRect.setSize(scaledTileSize); // Check and see if a single draw of the image can cover the entire area we are supposed to tile. if (oneTileRect.contains(destRect) && !ctxt.drawLuminanceMask()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, blendMode, ImageOrientationDescription()); return; } #if PLATFORM(IOS) // When using accelerated drawing on iOS, it's faster to stretch an image than to tile it. if (ctxt.isAcceleratedContext()) { if (size().width() == 1 && intersection(oneTileRect, destRect).height() == destRect.height()) { FloatRect visibleSrcRect; visibleSrcRect.setX(0); visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height()); visibleSrcRect.setWidth(1); visibleSrcRect.setHeight(destRect.height() / scale.height()); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } if (size().height() == 1 && intersection(oneTileRect, destRect).width() == destRect.width()) { FloatRect visibleSrcRect; visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width()); visibleSrcRect.setY(0); visibleSrcRect.setWidth(destRect.width() / scale.width()); visibleSrcRect.setHeight(1); draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, ImageOrientationDescription()); return; } } #endif // Patterned images and gradients can use lots of memory for caching when the // tile size is large (<rdar://problem/4691859>, <rdar://problem/6239505>). // Memory consumption depends on the transformed tile size which can get // larger than the original tile if user zooms in enough. #if PLATFORM(IOS) const float maxPatternTilePixels = 512 * 512; #else const float maxPatternTilePixels = 2048 * 2048; #endif FloatRect transformedTileSize = ctxt.getCTM().mapRect(FloatRect(FloatPoint(), scaledTileSize)); float transformedTileSizePixels = transformedTileSize.width() * transformedTileSize.height(); FloatRect currentTileRect = oneTileRect; if (transformedTileSizePixels > maxPatternTilePixels) { GraphicsContextStateSaver stateSaver(ctxt); ctxt.clip(destRect); currentTileRect.shiftYEdgeTo(destRect.y()); float toY = currentTileRect.y(); while (toY < destRect.maxY()) { currentTileRect.shiftXEdgeTo(destRect.x()); float toX = currentTileRect.x(); while (toX < destRect.maxX()) { FloatRect toRect(toX, toY, currentTileRect.width(), currentTileRect.height()); FloatRect fromRect(toFloatPoint(currentTileRect.location() - oneTileRect.location()), currentTileRect.size()); fromRect.scale(1 / scale.width(), 1 / scale.height()); draw(ctxt, toRect, fromRect, op, BlendModeNormal, ImageOrientationDescription()); toX += currentTileRect.width(); currentTileRect.shiftXEdgeTo(oneTileRect.x()); } toY += currentTileRect.height(); currentTileRect.shiftYEdgeTo(oneTileRect.y()); } return; } AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), spacing, op, destRect, blendMode); #if PLATFORM(IOS) startAnimation(DoNotCatchUp); #else startAnimation(); #endif }
void RootFrameViewport::updateScrollAnimator() { scrollAnimator()->setCurrentPosition(toFloatPoint(scrollOffsetFromScrollAnimators())); }