void ScrollableArea::scrollToXOffsetWithoutAnimation(float x) { scrollToOffsetWithoutAnimation(FloatPoint(x, m_scrollAnimator->currentPosition().y())); }
WebCompositorInputHandlerImpl::EventDisposition WebCompositorInputHandlerImpl::handleGestureFling(const WebGestureEvent& gestureEvent) { WebInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(WebPoint(gestureEvent.x, gestureEvent.y), WebInputHandlerClient::ScrollInputTypeGesture); switch (scrollStatus) { case WebInputHandlerClient::ScrollStatusStarted: { m_inputHandlerClient->scrollEnd(); m_wheelFlingCurve = PlatformGestureCurveFactory::get()->createCurve(gestureEvent.data.flingStart.sourceDevice, FloatPoint(gestureEvent.data.flingStart.velocityX, gestureEvent.data.flingStart.velocityY)); TRACE_EVENT_ASYNC_BEGIN1("cc", "WebCompositorInputHandlerImpl::handleGestureFling::started", this, "curve", m_wheelFlingCurve->debugName()); m_wheelFlingParameters.delta = WebFloatPoint(gestureEvent.data.flingStart.velocityX, gestureEvent.data.flingStart.velocityY); m_wheelFlingParameters.point = WebPoint(gestureEvent.x, gestureEvent.y); m_wheelFlingParameters.globalPoint = WebPoint(gestureEvent.globalX, gestureEvent.globalY); m_wheelFlingParameters.modifiers = gestureEvent.modifiers; m_wheelFlingParameters.sourceDevice = gestureEvent.data.flingStart.sourceDevice; m_inputHandlerClient->scheduleAnimation(); return DidHandle; } case WebInputHandlerClient::ScrollStatusOnMainThread: { TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::handleGestureFling::scrollOnMainThread"); return DidNotHandle; } case WebInputHandlerClient::ScrollStatusIgnored: { TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::handleGestureFling::ignored"); // We still pass the curve to the main thread if there's nothing scrollable, in case something // registers a handler before the curve is over. return DidNotHandle; } } return DidNotHandle; }
FloatPoint Path::currentPoint() const { // FIXME: return current point of subpath. float quietNaN = std::numeric_limits<float>::quiet_NaN(); return FloatPoint(quietNaN, quietNaN); }
void TileController::setTopContentInset(float topContentInset) { m_topContentInset = topContentInset; setTiledScrollingIndicatorPosition(FloatPoint(0, m_topContentInset)); }
void GraphicsLayerCACF::updateAnchorPoint() { primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())); primaryLayer()->setAnchorPointZ(m_anchorPoint.z()); updateLayerPosition(); }
void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius) { bool equalWidths = (topLeftRadius.width() == topRightRadius.width() && topRightRadius.width() == bottomLeftRadius.width() && bottomLeftRadius.width() == bottomRightRadius.width()); bool equalHeights = (topLeftRadius.height() == bottomLeftRadius.height() && bottomLeftRadius.height() == topRightRadius.height() && topRightRadius.height() == bottomRightRadius.height()); if (equalWidths && equalHeights) { CGPathAddRoundedRect(m_path, 0, rect, topLeftRadius.width(), topLeftRadius.height()); return; } moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y())); addLineTo(FloatPoint(rect.maxX() - topRightRadius.width(), rect.y())); addBezierCurveTo(FloatPoint(rect.maxX() - topRightRadius.width() * gCircleControlPoint, rect.y()), FloatPoint(rect.maxX(), rect.y() + topRightRadius.height() * gCircleControlPoint), FloatPoint(rect.maxX(), rect.y() + topRightRadius.height())); addLineTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height())); addBezierCurveTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * gCircleControlPoint), FloatPoint(rect.maxX() - bottomRightRadius.width() * gCircleControlPoint, rect.maxY()), FloatPoint(rect.maxX() - bottomRightRadius.width(), rect.maxY())); addLineTo(FloatPoint(rect.x() + bottomLeftRadius.width(), rect.maxY())); addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * gCircleControlPoint, rect.maxY()), FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height() * gCircleControlPoint), FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height())); addLineTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height())); addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * gCircleControlPoint), FloatPoint(rect.x() + topLeftRadius.width() * gCircleControlPoint, rect.y()), FloatPoint(rect.x() + topLeftRadius.width(), rect.y())); closeSubpath(); }
LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo) : m_columnInfo(columnInfo) , m_lineGrid(0) , m_next(prev) #if ENABLE(CSS_SHAPES) , m_exclusionShapeInsideInfo(0) #endif #ifndef NDEBUG , m_renderer(renderer) #endif { ASSERT(m_next); bool fixed = renderer->isOutOfFlowPositioned() && renderer->style()->position() == FixedPosition; if (fixed) { // FIXME: This doesn't work correctly with transforms. FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), IsFixed); m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset; } else m_paintOffset = prev->m_paintOffset + offset; if (renderer->isOutOfFlowPositioned() && !fixed) { if (RenderObject* container = renderer->container()) { if (container->isInFlowPositioned() && container->isRenderInline()) m_paintOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer); } } m_layoutOffset = m_paintOffset; if (renderer->hasPaintOffset() && renderer->hasLayer()) m_paintOffset += renderer->layer()->paintOffset(); m_clipped = !fixed && prev->m_clipped; if (m_clipped) m_clipRect = prev->m_clipRect; if (renderer->hasOverflowClip()) { LayoutRect clipRect(toPoint(m_paintOffset) + renderer->view()->layoutDelta(), renderer->cachedSizeForOverflowClip()); if (m_clipped) m_clipRect.intersect(clipRect); else { m_clipRect = clipRect; m_clipped = true; } m_paintOffset -= renderer->scrolledContentOffset(); } // If we establish a new page height, then cache the offset to the top of the first page. // We can compare this later on to figure out what part of the page we're actually on, if (pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread()) { m_pageLogicalHeight = pageLogicalHeight; bool isFlipped = renderer->style()->isFlippedBlocksWritingMode(); m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()), m_layoutOffset.height() + (!isFlipped ? renderer->borderTop() + renderer->paddingTop() : renderer->borderBottom() + renderer->paddingBottom())); m_pageLogicalHeightChanged = pageLogicalHeightChanged; } else { // If we don't establish a new page height, then propagate the old page height and offset down. m_pageLogicalHeight = m_next->m_pageLogicalHeight; m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged; m_pageOffset = m_next->m_pageOffset; // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and // writing mode roots. if (renderer->isUnsplittableForPagination()) m_pageLogicalHeight = 0; } // Propagate line grid information. propagateLineGridInfo(renderer); if (!m_columnInfo) m_columnInfo = m_next->m_columnInfo; #if ENABLE(CSS_SHAPES) if (renderer->isRenderBlock()) { const RenderBlock* renderBlock = toRenderBlock(renderer); m_exclusionShapeInsideInfo = renderBlock->exclusionShapeInsideInfo(); if (!m_exclusionShapeInsideInfo && m_next->m_exclusionShapeInsideInfo && renderBlock->allowsExclusionShapeInsideInfoSharing()) m_exclusionShapeInsideInfo = m_next->m_exclusionShapeInsideInfo; } #endif m_layoutDelta = m_next->m_layoutDelta; #if !ASSERT_DISABLED && ENABLE(SATURATED_LAYOUT_ARITHMETIC) m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated; m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated; #endif m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread(); if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis()) computeLineGridPaginationOrigin(renderer); // If we have a new grid to track, then add it to our set. if (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow()) establishLineGrid(toRenderBlock(renderer)); // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present. }
FloatPoint Sprite::getOrigin() const { return FloatPoint(_sprite->getOrigin().x, _sprite->getOrigin().y); }
FloatPoint Sprite::getScale() const { return FloatPoint(_sprite->getScale().x, _sprite->getScale().y); }
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { LayoutPoint pointInParent = locationInContainer.point() - toLayoutSize(accumulatedOffset); LayoutPoint pointInBorderBox = pointInParent - toLayoutSize(location()); // Only test SVG content if the point is in our content box. // FIXME: This should be an intersection when rect-based hit tests are supported by nodeAtFloatPoint. if (contentBoxRect().contains(pointInBorderBox)) { FloatPoint localPoint = localToParentTransform().inverse().valueOr(AffineTransform()).mapPoint(FloatPoint(pointInParent)); for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { updateHitTestResult(result, pointInBorderBox); if (!result.addNodeToRectBasedTestResult(child->node(), request, locationInContainer)) return true; } } } // If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit. if (hitTestAction == HitTestBlockBackground && visibleToHitTesting()) { // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase, // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able // to detect these hits anymore. LayoutRect boundsRect(accumulatedOffset + location(), size()); if (locationInContainer.intersects(boundsRect)) { updateHitTestResult(result, pointInBorderBox); if (!result.addNodeToRectBasedTestResult(&svgSVGElement(), request, locationInContainer, boundsRect)) return true; } } return false; }
FloatPoint Sprite::getPosition() const { return FloatPoint(_sprite->getPosition().x, _sprite->getPosition().y); }
// Helper functions static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& b, float progress) { return FloatPoint(blend(a.x(), b.x(), progress), blend(a.y(), b.y(), progress)); }
FloatPoint FloatPoint::narrowPrecision(double x, double y) { return FloatPoint(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y)); }
void ScrollableArea::scrollToYOffsetWithoutAnimation(float y) { scrollToOffsetWithoutAnimation(FloatPoint(m_scrollAnimator->currentPosition().x(), y)); }
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { cairo_t* cr = context->platformContext(); cairo_save(cr); cairo_set_scaled_font(cr, font->platformData().scaledFont()); GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from); float offset = 0.0f; for (int i = 0; i < numGlyphs; i++) { glyphs[i].x = offset; glyphs[i].y = 0.0f; offset += glyphBuffer.advanceAt(from + i); } Color fillColor = context->fillColor(); // Synthetic Oblique if(font->platformData().syntheticOblique()) { cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()}; cairo_transform(cr, &mat); } else { cairo_translate(cr, point.x(), point.y()); } // Text shadow, inspired by FontMac FloatSize shadowOffset; float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() & cTextFill && context->getShadow(shadowOffset, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { // Disable graphics context shadows (not yet implemented) and paint them manually context->clearShadow(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); cairo_save(cr); float red, green, blue, alpha; shadowFillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); #if ENABLE(FILTERS) cairo_text_extents_t extents; cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents); FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height)); IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); // Draw shadow into a new ImageBuffer OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); GraphicsContext* shadowContext = shadowBuffer->context(); cairo_t* shadowCr = shadowContext->platformContext(); cairo_translate(shadowCr, radius, extents.height + radius); cairo_set_scaled_font(shadowCr, font->platformData().scaledFont()); cairo_show_glyphs(shadowCr, glyphs, numGlyphs); if (font->syntheticBoldOffset()) { cairo_save(shadowCr); cairo_translate(shadowCr, font->syntheticBoldOffset(), 0); cairo_show_glyphs(shadowCr, glyphs, numGlyphs); cairo_restore(shadowCr); } cairo_translate(cr, 0.0, -extents.height); context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); #else cairo_translate(cr, shadowOffset.width(), shadowOffset.height()); cairo_show_glyphs(cr, glyphs, numGlyphs); if (font->syntheticBoldOffset()) { cairo_save(cr); cairo_translate(cr, font->syntheticBoldOffset(), 0); cairo_show_glyphs(cr, glyphs, numGlyphs); cairo_restore(cr); } #endif cairo_restore(cr); } if (context->textDrawingMode() & cTextFill) { if (context->fillGradient()) { cairo_set_source(cr, context->fillGradient()->platformGradient()); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); cairo_paint_with_alpha(cr, context->getAlpha()); cairo_pop_group_to_source(cr); } } else if (context->fillPattern()) { AffineTransform affine; cairo_pattern_t* pattern = context->fillPattern()->createPlatformPattern(affine); cairo_set_source(cr, pattern); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); cairo_paint_with_alpha(cr, context->getAlpha()); cairo_pop_group_to_source(cr); } cairo_pattern_destroy(pattern); } else { float red, green, blue, alpha; fillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha()); } cairo_show_glyphs(cr, glyphs, numGlyphs); if (font->syntheticBoldOffset()) { cairo_save(cr); cairo_translate(cr, font->syntheticBoldOffset(), 0); cairo_show_glyphs(cr, glyphs, numGlyphs); cairo_restore(cr); } } // Prevent running into a long computation within cairo. If the stroke width is // twice the size of the width of the text we will not ask cairo to stroke // the text as even one single stroke would cover the full wdth of the text. // See https://bugs.webkit.org/show_bug.cgi?id=33759. if (context->textDrawingMode() & cTextStroke && context->strokeThickness() < 2 * offset) { if (context->strokeGradient()) { cairo_set_source(cr, context->strokeGradient()->platformGradient()); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); cairo_paint_with_alpha(cr, context->getAlpha()); cairo_pop_group_to_source(cr); } } else if (context->strokePattern()) { AffineTransform affine; cairo_pattern_t* pattern = context->strokePattern()->createPlatformPattern(affine); cairo_set_source(cr, pattern); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); cairo_paint_with_alpha(cr, context->getAlpha()); cairo_pop_group_to_source(cr); } cairo_pattern_destroy(pattern); } else { Color strokeColor = context->strokeColor(); float red, green, blue, alpha; strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha()); } cairo_glyph_path(cr, glyphs, numGlyphs); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Re-enable the platform shadow we disabled earlier if (hasShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace); cairo_restore(cr); }
void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { if (isEmpty()) return; cairo_t* cr = platformPath()->context(); double x0, y0; cairo_get_current_point(cr, &x0, &y0); FloatPoint p0(x0, y0); // Draw only a straight line to p1 if any of the points are equal or the radius is zero // or the points are collinear (triangle that the points form has area of zero value). if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || !radius || !areaOfTriangleFormedByPoints(p0, p1, p2)) { cairo_line_to(cr, p1.x(), p1.y()); return; } FloatPoint p1p0((p0.x() - p1.x()),(p0.y() - p1.y())); FloatPoint p1p2((p2.x() - p1.x()),(p2.y() - p1.y())); float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y()); float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y()); double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length); // all points on a line logic if (cos_phi == -1) { cairo_line_to(cr, p1.x(), p1.y()); return; } if (cos_phi == 1) { // add infinite far away point unsigned int max_length = 65535; double factor_max = max_length / p1p0_length; FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y())); cairo_line_to(cr, ep.x(), ep.y()); return; } float tangent = radius / tan(acos(cos_phi) / 2); float factor_p1p0 = tangent / p1p0_length; FloatPoint t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y())); FloatPoint orth_p1p0(p1p0.y(), -p1p0.x()); float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y()); float factor_ra = radius / orth_p1p0_length; // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0 double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length); if (cos_alpha < 0.f) orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y()); FloatPoint p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y())); // calculate angles for addArc orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y()); float sa = acos(orth_p1p0.x() / orth_p1p0_length); if (orth_p1p0.y() < 0.f) sa = 2 * piDouble - sa; // anticlockwise logic bool anticlockwise = false; float factor_p1p2 = tangent / p1p2_length; FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y())); FloatPoint orth_p1p2((t_p1p2.x() - p.x()),(t_p1p2.y() - p.y())); float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y()); float ea = acos(orth_p1p2.x() / orth_p1p2_length); if (orth_p1p2.y() < 0) ea = 2 * piDouble - ea; if ((sa > ea) && ((sa - ea) < piDouble)) anticlockwise = true; if ((sa < ea) && ((ea - sa) > piDouble)) anticlockwise = true; cairo_line_to(cr, t_p1p0.x(), t_p1p0.y()); addArc(p, radius, sa, ea, anticlockwise); }
Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii) { Path path; float x = rectangle.x(); float y = rectangle.y(); float width = rectangle.width(); float height = rectangle.height(); float rx = roundingRadii.width(); float ry = roundingRadii.height(); if (width <= 0.0f || height <= 0.0f) return path; float dx = rx, dy = ry; // If rx is greater than half of the width of the rectangle // then set rx to half of the width (required in SVG spec) if (dx > width * 0.5f) dx = width * 0.5f; // If ry is greater than half of the height of the rectangle // then set ry to half of the height (required in SVG spec) if (dy > height * 0.5f) dy = height * 0.5f; path.moveTo(FloatPoint(x + dx, y)); if (dx < width * 0.5f) path.addLineTo(FloatPoint(x + width - rx, y)); path.addBezierCurveTo(FloatPoint(x + width - dx * (1 - QUARTER), y), FloatPoint(x + width, y + dy * (1 - QUARTER)), FloatPoint(x + width, y + dy)); if (dy < height * 0.5) path.addLineTo(FloatPoint(x + width, y + height - dy)); path.addBezierCurveTo(FloatPoint(x + width, y + height - dy * (1 - QUARTER)), FloatPoint(x + width - dx * (1 - QUARTER), y + height), FloatPoint(x + width - dx, y + height)); if (dx < width * 0.5) path.addLineTo(FloatPoint(x + dx, y + height)); path.addBezierCurveTo(FloatPoint(x + dx * (1 - QUARTER), y + height), FloatPoint(x, y + height - dy * (1 - QUARTER)), FloatPoint(x, y + height - dy)); if (dy < height * 0.5) path.addLineTo(FloatPoint(x, y + dy)); path.addBezierCurveTo(FloatPoint(x, y + dy * (1 - QUARTER)), FloatPoint(x + dx * (1 - QUARTER), y), FloatPoint(x + dx, y)); path.closeSubpath(); return path; }
PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, Length margin, Length padding) { ASSERT(basicShape); bool horizontalWritingMode = isHorizontalWritingMode(writingMode); float boxWidth = horizontalWritingMode ? logicalBoxSize.width() : logicalBoxSize.height(); float boxHeight = horizontalWritingMode ? logicalBoxSize.height() : logicalBoxSize.width(); OwnPtr<Shape> shape; switch (basicShape->type()) { case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); float centerX = floatValueForCenterCoordinate(circle->centerX(), boxWidth); float centerY = floatValueForCenterCoordinate(circle->centerY(), boxHeight); float radius = circle->floatValueForRadiusInBox(boxWidth, boxHeight); FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode); shape = createCircleShape(logicalCenter, radius); break; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); float centerX = floatValueForCenterCoordinate(ellipse->centerX(), boxWidth); float centerY = floatValueForCenterCoordinate(ellipse->centerY(), boxHeight); float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), centerX, boxWidth); float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), centerY, boxHeight); FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode); shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY)); break; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon& polygon = *static_cast<const BasicShapePolygon*>(basicShape); const Vector<Length>& values = polygon.values(); size_t valuesSize = values.size(); ASSERT(!(valuesSize % 2)); OwnPtr<Vector<FloatPoint>> vertices = adoptPtr(new Vector<FloatPoint>(valuesSize / 2)); for (unsigned i = 0; i < valuesSize; i += 2) { FloatPoint vertex( floatValueForLength(values.at(i), boxWidth), floatValueForLength(values.at(i + 1), boxHeight)); (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height(), writingMode); } shape = createPolygonShape(vertices.release(), polygon.windRule()); break; } case BasicShape::BasicShapeInsetType: { const BasicShapeInset& inset = *static_cast<const BasicShapeInset*>(basicShape); float left = floatValueForLength(inset.left(), boxWidth); float top = floatValueForLength(inset.top(), boxHeight); FloatRect rect(left, top, std::max<float>(boxWidth - left - floatValueForLength(inset.right(), boxWidth), 0), std::max<float>(boxHeight - top - floatValueForLength(inset.bottom(), boxHeight), 0)); FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.height(), writingMode); FloatSize boxSize(boxWidth, boxHeight); FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topLeftRadius(), boxSize), writingMode); FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topRightRadius(), boxSize), writingMode); FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomLeftRadius(), boxSize), writingMode); FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomRightRadius(), boxSize), writingMode); FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerRadii)); shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii)); break; } default: ASSERT_NOT_REACHED(); } shape->m_writingMode = writingMode; shape->m_margin = floatValueForLength(margin, 0); shape->m_padding = floatValueForLength(padding, 0); return shape.release(); }
void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const { if (m_position != FloatPoint()) { writeIndent(ts, indent + 1); ts << "(position " << m_position.x() << " " << m_position.y() << ")\n"; } if (m_anchorPoint != FloatPoint3D(0.5f, 0.5f, 0)) { writeIndent(ts, indent + 1); ts << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y() << ")\n"; } if (m_size != IntSize()) { writeIndent(ts, indent + 1); ts << "(bounds " << m_size.width() << " " << m_size.height() << ")\n"; } if (m_opacity != 1) { writeIndent(ts, indent + 1); ts << "(opacity " << m_opacity << ")\n"; } if (m_usingTiledLayer) { writeIndent(ts, indent + 1); ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n"; } if (m_preserves3D) { writeIndent(ts, indent + 1); ts << "(preserves3D " << m_preserves3D << ")\n"; } if (m_drawsContent) { writeIndent(ts, indent + 1); ts << "(drawsContent " << m_drawsContent << ")\n"; } if (!m_backfaceVisibility) { writeIndent(ts, indent + 1); ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n"; } if (behavior & LayerTreeAsTextDebug) { writeIndent(ts, indent + 1); ts << "("; if (m_client) ts << "client " << static_cast<void*>(m_client); else ts << "no client"; ts << ")\n"; } if (m_backgroundColorSet) { writeIndent(ts, indent + 1); ts << "(backgroundColor " << m_backgroundColor.name() << ")\n"; } if (!m_transform.isIdentity()) { writeIndent(ts, indent + 1); ts << "(transform "; ts << "[" << m_transform.m11() << " " << m_transform.m12() << " " << m_transform.m13() << " " << m_transform.m14() << "] "; ts << "[" << m_transform.m21() << " " << m_transform.m22() << " " << m_transform.m23() << " " << m_transform.m24() << "] "; ts << "[" << m_transform.m31() << " " << m_transform.m32() << " " << m_transform.m33() << " " << m_transform.m34() << "] "; ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "])\n"; } // Avoid dumping the sublayer transform on the root layer, because it's used for geometry flipping, whose behavior // differs between platforms. if (parent() && !m_childrenTransform.isIdentity()) { writeIndent(ts, indent + 1); ts << "(childrenTransform "; ts << "[" << m_childrenTransform.m11() << " " << m_childrenTransform.m12() << " " << m_childrenTransform.m13() << " " << m_childrenTransform.m14() << "] "; ts << "[" << m_childrenTransform.m21() << " " << m_childrenTransform.m22() << " " << m_childrenTransform.m23() << " " << m_childrenTransform.m24() << "] "; ts << "[" << m_childrenTransform.m31() << " " << m_childrenTransform.m32() << " " << m_childrenTransform.m33() << " " << m_childrenTransform.m34() << "] "; ts << "[" << m_childrenTransform.m41() << " " << m_childrenTransform.m42() << " " << m_childrenTransform.m43() << " " << m_childrenTransform.m44() << "])\n"; } if (m_replicaLayer) { writeIndent(ts, indent + 1); ts << "(replica layer"; if (behavior & LayerTreeAsTextDebug) ts << " " << m_replicaLayer; ts << ")\n"; m_replicaLayer->dumpLayer(ts, indent + 2, behavior); } if (m_replicatedLayer) { writeIndent(ts, indent + 1); ts << "(replicated layer"; if (behavior & LayerTreeAsTextDebug) ts << " " << m_replicatedLayer;; ts << ")\n"; } if (m_children.size()) { writeIndent(ts, indent + 1); ts << "(children " << m_children.size() << "\n"; unsigned i; for (i = 0; i < m_children.size(); i++) m_children[i]->dumpLayer(ts, indent + 2, behavior); writeIndent(ts, indent + 1); ts << ")\n"; } }
void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const { if (wasFixed) *wasFixed = false; quads.append(FloatRect(FloatPoint(), layer()->size())); }
void MouseRelatedEvent::computePageLocation() { float zoomFactor = pageZoomFactor(this); setAbsoluteLocation(roundedIntPoint(FloatPoint(pageX() * zoomFactor, pageY() * zoomFactor))); }
bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode, bool checkForInitialMoveTo) { ASSERT(m_source); ASSERT(m_consumer); m_pathParsingMode = pathParsingMode; m_controlPoint = FloatPoint(); m_currentPoint = FloatPoint(); m_subPathPoint = FloatPoint(); m_closePath = true; // Skip any leading spaces. if (!m_source->moveToNextToken()) return false; SVGPathSegType command; m_source->parseSVGSegmentType(command); m_lastCommand = PathSegUnknown; // Path must start with moveto. if (checkForInitialMoveTo && command != PathSegMoveToAbs && command != PathSegMoveToRel) return false; while (true) { // Skip spaces between command and first coordinate. m_source->moveToNextToken(); m_mode = AbsoluteCoordinates; switch (command) { case PathSegMoveToRel: m_mode = RelativeCoordinates; case PathSegMoveToAbs: if (!parseMoveToSegment()) return false; break; case PathSegLineToRel: m_mode = RelativeCoordinates; case PathSegLineToAbs: if (!parseLineToSegment()) return false; break; case PathSegLineToHorizontalRel: m_mode = RelativeCoordinates; case PathSegLineToHorizontalAbs: if (!parseLineToHorizontalSegment()) return false; break; case PathSegLineToVerticalRel: m_mode = RelativeCoordinates; case PathSegLineToVerticalAbs: if (!parseLineToVerticalSegment()) return false; break; case PathSegClosePath: parseClosePathSegment(); break; case PathSegCurveToCubicRel: m_mode = RelativeCoordinates; case PathSegCurveToCubicAbs: if (!parseCurveToCubicSegment()) return false; break; case PathSegCurveToCubicSmoothRel: m_mode = RelativeCoordinates; case PathSegCurveToCubicSmoothAbs: if (!parseCurveToCubicSmoothSegment()) return false; break; case PathSegCurveToQuadraticRel: m_mode = RelativeCoordinates; case PathSegCurveToQuadraticAbs: if (!parseCurveToQuadraticSegment()) return false; break; case PathSegCurveToQuadraticSmoothRel: m_mode = RelativeCoordinates; case PathSegCurveToQuadraticSmoothAbs: if (!parseCurveToQuadraticSmoothSegment()) return false; break; case PathSegArcRel: m_mode = RelativeCoordinates; case PathSegArcAbs: if (!parseArcToSegment()) return false; break; default: return false; } if (!m_consumer->continueConsuming()) return true; m_lastCommand = command; if (!m_source->hasMoreData()) return true; command = m_source->nextCommand(command); if (m_lastCommand != PathSegCurveToCubicAbs && m_lastCommand != PathSegCurveToCubicRel && m_lastCommand != PathSegCurveToCubicSmoothAbs && m_lastCommand != PathSegCurveToCubicSmoothRel && m_lastCommand != PathSegCurveToQuadraticAbs && m_lastCommand != PathSegCurveToQuadraticRel && m_lastCommand != PathSegCurveToQuadraticSmoothAbs && m_lastCommand != PathSegCurveToQuadraticSmoothRel) m_controlPoint = m_currentPoint; m_consumer->incrementPathSegmentCount(); } return false; }
void TileController::adjustTileCoverageRect(FloatRect& coverageRect, const FloatSize& newSize, const FloatRect& previousVisibleRect, const FloatRect& visibleRect, float contentsScale) const { // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect. if (!m_isInWindow) { coverageRect = visibleRect; return; } #if PLATFORM(IOS) // FIXME: unify the iOS and Mac code. UNUSED_PARAM(previousVisibleRect); if (m_tileCoverage == CoverageForVisibleArea || MemoryPressureHandler::singleton().isUnderMemoryPressure()) { coverageRect = visibleRect; return; } double horizontalMargin = tileSize().width() / contentsScale; double verticalMargin = tileSize().height() / contentsScale; double currentTime = monotonicallyIncreasingTime(); double timeDelta = currentTime - m_velocity.lastUpdateTime; FloatRect futureRect = visibleRect; futureRect.setLocation(FloatPoint( futureRect.location().x() + timeDelta * m_velocity.horizontalVelocity, futureRect.location().y() + timeDelta * m_velocity.verticalVelocity)); if (m_velocity.horizontalVelocity) { futureRect.setWidth(futureRect.width() + horizontalMargin); if (m_velocity.horizontalVelocity < 0) futureRect.setX(futureRect.x() - horizontalMargin); } if (m_velocity.verticalVelocity) { futureRect.setHeight(futureRect.height() + verticalMargin); if (m_velocity.verticalVelocity < 0) futureRect.setY(futureRect.y() - verticalMargin); } if (!m_velocity.horizontalVelocity && !m_velocity.verticalVelocity) { if (m_velocity.scaleChangeRate > 0) { coverageRect = visibleRect; return; } futureRect.setWidth(futureRect.width() + horizontalMargin); futureRect.setHeight(futureRect.height() + verticalMargin); futureRect.setX(futureRect.x() - horizontalMargin / 2); futureRect.setY(futureRect.y() - verticalMargin / 2); } // Can't use m_tileCacheLayer->bounds() here, because the size of the underlying platform layer // hasn't been updated for the current commit. IntSize contentSize = expandedIntSize(newSize); if (futureRect.maxX() > contentSize.width()) futureRect.setX(contentSize.width() - futureRect.width()); if (futureRect.maxY() > contentSize.height()) futureRect.setY(contentSize.height() - futureRect.height()); if (futureRect.x() < 0) futureRect.setX(0); if (futureRect.y() < 0) futureRect.setY(0); coverageRect.unite(futureRect); return; #else UNUSED_PARAM(contentsScale); // FIXME: look at how far the document can scroll in each dimension. FloatSize coverageSize = visibleRect.size(); bool largeVisibleRectChange = !previousVisibleRect.isEmpty() && !visibleRect.intersects(previousVisibleRect); // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height. // These values were chosen because it's more common to have tall pages and to scroll vertically, // so we keep more tiles above and below the current area. float widthScale = 1; float heightScale = 1; if (m_tileCoverage & CoverageForHorizontalScrolling && !largeVisibleRectChange) widthScale = 2; if (m_tileCoverage & CoverageForVerticalScrolling && !largeVisibleRectChange) heightScale = 3; coverageSize.scale(widthScale, heightScale); FloatRect coverageBounds = boundsForSize(newSize); FloatRect coverage = expandRectWithinRect(visibleRect, coverageSize, coverageBounds); LOG_WITH_STREAM(Scrolling, stream << "TileController::computeTileCoverageRect newSize=" << newSize << " mode " << m_tileCoverage << " expanded to " << coverageSize << " bounds with margin " << coverageBounds << " coverage " << coverage); coverageRect.unite(coverage); #endif }
// This works by converting the SVG arc to "simple" beziers. // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, FloatPoint& point1, FloatPoint& point2, bool largeArcFlag, bool sweepFlag) { FloatSize midPointDistance = point1 - point2; midPointDistance.scale(0.5f); AffineTransform pointTransform; pointTransform.rotate(-angle); FloatPoint transformedMidPoint = pointTransform.mapPoint(FloatPoint(midPointDistance.width(), midPointDistance.height())); float squareRx = rx * rx; float squareRy = ry * ry; float squareX = transformedMidPoint.x() * transformedMidPoint.x(); float squareY = transformedMidPoint.y() * transformedMidPoint.y(); // Check if the radii are big enough to draw the arc, scale radii if not. // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii float radiiScale = squareX / squareRx + squareY / squareRy; if (radiiScale > 1) { rx *= sqrtf(radiiScale); ry *= sqrtf(radiiScale); } pointTransform.makeIdentity(); pointTransform.scale(1 / rx, 1 / ry); pointTransform.rotate(-angle); point1 = pointTransform.mapPoint(point1); point2 = pointTransform.mapPoint(point2); FloatSize delta = point2 - point1; float d = delta.width() * delta.width() + delta.height() * delta.height(); float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f); float scaleFactor = sqrtf(scaleFactorSquared); if (sweepFlag == largeArcFlag) scaleFactor = -scaleFactor; delta.scale(scaleFactor); FloatPoint centerPoint = point1 + point2; centerPoint.scale(0.5f, 0.5f); centerPoint.move(-delta.height(), delta.width()); float theta1 = FloatPoint(point1 - centerPoint).slopeAngleRadians(); float theta2 = FloatPoint(point2 - centerPoint).slopeAngleRadians(); float thetaArc = theta2 - theta1; if (thetaArc < 0 && sweepFlag) thetaArc += 2 * piFloat; else if (thetaArc > 0 && !sweepFlag) thetaArc -= 2 * piFloat; pointTransform.makeIdentity(); pointTransform.rotate(angle); pointTransform.scale(rx, ry); // Some results of atan2 on some platform implementations are not exact enough. So that we get more // cubic curves than expected here. Adding 0.001f reduces the count of sgements to the correct count. int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f))); for (int i = 0; i < segments; ++i) { float startTheta = theta1 + i * thetaArc / segments; float endTheta = theta1 + (i + 1) * thetaArc / segments; float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta)); if (!std::isfinite(t)) return false; float sinStartTheta = sinf(startTheta); float cosStartTheta = cosf(startTheta); float sinEndTheta = sinf(endTheta); float cosEndTheta = cosf(endTheta); point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta); point1.move(centerPoint.x(), centerPoint.y()); FloatPoint targetPoint = FloatPoint(cosEndTheta, sinEndTheta); targetPoint.move(centerPoint.x(), centerPoint.y()); point2 = targetPoint; point2.move(t * sinEndTheta, -t * cosEndTheta); m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform.mapPoint(point2), pointTransform.mapPoint(targetPoint), AbsoluteCoordinates); } return true; }
FloatPoint massCenter() const { return FloatPoint(cx, cy); }
FloatPoint SVGSVGElement::createSVGPoint() { return FloatPoint(); }
FloatRect WebChromeClient::pageRect() { return FloatRect(FloatPoint(), m_page->size()); }
void SVGDocument::startPan(const FloatPoint& start) { if (rootElement()) m_translate = FloatPoint(start.x() - rootElement()->currentTranslate().x(), rootElement()->currentTranslate().y() + start.y()); }
PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode) { if (!basicShape) return nullptr; bool horizontalWritingMode = isHorizontalWritingMode(writingMode); float boxWidth = horizontalWritingMode ? logicalBoxWidth : logicalBoxHeight; float boxHeight = horizontalWritingMode ? logicalBoxHeight : logicalBoxWidth; OwnPtr<ExclusionShape> exclusionShape; switch (basicShape->type()) { case BasicShape::BASIC_SHAPE_RECTANGLE: { const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); float x = floatValueForLength(rectangle->x(), boxWidth); float y = floatValueForLength(rectangle->y(), boxHeight); float width = floatValueForLength(rectangle->width(), boxWidth); float height = floatValueForLength(rectangle->height(), boxHeight); Length radiusXLength = rectangle->cornerRadiusX(); Length radiusYLength = rectangle->cornerRadiusY(); float radiusX = radiusXLength.isUndefined() ? 0 : floatValueForLength(radiusXLength, boxWidth); float radiusY = radiusYLength.isUndefined() ? 0 : floatValueForLength(radiusYLength, boxHeight); exclusionShape = horizontalWritingMode ? createExclusionRectangle(FloatRect(x, y, width, height), FloatSize(radiusX, radiusY)) : createExclusionRectangle(FloatRect(y, x, height, width), FloatSize(radiusY, radiusX)); break; } case BasicShape::BASIC_SHAPE_CIRCLE: { const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); float centerX = floatValueForLength(circle->centerX(), boxWidth); float centerY = floatValueForLength(circle->centerY(), boxHeight); float radius = floatValueForLength(circle->radius(), std::max(boxHeight, boxWidth)); exclusionShape = horizontalWritingMode ? createExclusionCircle(FloatPoint(centerX, centerY), radius) : createExclusionCircle(FloatPoint(centerY, centerX), radius); break; } case BasicShape::BASIC_SHAPE_ELLIPSE: { const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); float centerX = floatValueForLength(ellipse->centerX(), boxWidth); float centerY = floatValueForLength(ellipse->centerY(), boxHeight); float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth); float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight); exclusionShape = horizontalWritingMode ? createExclusionEllipse(FloatPoint(centerX, centerY), FloatSize(radiusX, radiusY)) : createExclusionEllipse(FloatPoint(centerY, centerX), FloatSize(radiusY, radiusX)); break; } case BasicShape::BASIC_SHAPE_POLYGON: { const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); const Vector<Length>& values = polygon->values(); size_t valuesSize = values.size(); ASSERT(!(valuesSize % 2)); Vector<FloatPoint>* vertices = new Vector<FloatPoint>(valuesSize / 2); for (unsigned i = 0; i < valuesSize; i += 2) { FloatPoint vertex( floatValueForLength(values.at(i), boxWidth), floatValueForLength(values.at(i + 1), boxHeight)); (*vertices)[i / 2] = horizontalWritingMode ? vertex : vertex.transposedPoint(); } exclusionShape = createExclusionPolygon(adoptPtr(vertices), polygon->windRule()); break; } default: ASSERT_NOT_REACHED(); } exclusionShape->m_logicalBoxWidth = logicalBoxWidth; exclusionShape->m_logicalBoxHeight = logicalBoxHeight; exclusionShape->m_writingMode = writingMode; return exclusionShape.release(); }
void PinchViewport::reset() { setLocation(FloatPoint()); setScale(1); }