void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo) { if (!m_scrollLayerImpl) return; // Only send fake scroll/zoom deltas if we're pinch zooming out by a // significant amount. This also ensures only one fake delta set will be // sent. const float pinchZoomOutSensitivity = 0.95; if (m_pageScaleDelta > pinchZoomOutSensitivity) return; // Compute where the scroll offset/page scale would be if fully pinch-zoomed // out from the anchor point. FloatSize scrollBegin = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta()); scrollBegin.scale(m_pageScaleDelta); float scaleBegin = m_pageScale * m_pageScaleDelta; float pageScaleDeltaToSend = m_minPageScale / m_pageScale; FloatSize scaledContentsSize = contentSize(); scaledContentsSize.scale(pageScaleDeltaToSend); FloatSize anchor = toSize(m_previousPinchAnchor); FloatSize scrollEnd = scrollBegin + anchor; scrollEnd.scale(m_minPageScale / scaleBegin); scrollEnd -= anchor; scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_viewportSize)).expandedTo(FloatSize(0, 0)); scrollEnd.scale(1 / pageScaleDeltaToSend); makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale); }
void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const { FloatSize intrinsicSize; if (contentRenderer) { contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize); if (intrinsicRatio) ASSERT(!isPercentageIntrinsicSize); // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them. if (!isPercentageIntrinsicSize) { intrinsicSize.scale(style().effectiveZoom()); if (isRenderImage()) intrinsicSize.scale(toRenderImage(this)->imageDevicePixelRatio()); } if (hasAspectRatio() && isPercentageIntrinsicSize) intrinsicRatio = 1; // Update our intrinsic size to match what the content renderer has computed, so that when we // constrain the size below, the correct intrinsic size will be obtained for comparison against // min and max widths. if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty()) m_intrinsicSize = LayoutSize(intrinsicSize); if (!isHorizontalWritingMode()) { if (intrinsicRatio) intrinsicRatio = 1 / intrinsicRatio; intrinsicSize = intrinsicSize.transposedSize(); } } else { computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize); if (intrinsicRatio) { ASSERT(!isPercentageIntrinsicSize); if (!intrinsicSize.isEmpty()) m_intrinsicSize = LayoutSize(isHorizontalWritingMode() ? intrinsicSize : intrinsicSize.transposedSize()); } } // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along // each axis, the final returned size may in fact not preserve the aspect ratio. // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this // function was added, since all it has done is make the code more unclear. constrainedSize = intrinsicSize; if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty() && style().logicalWidth().isAuto() && style().logicalHeight().isAuto()) { // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom! constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height()); constrainedSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicSize.height() / intrinsicSize.width()); } }
void RotationViewportAnchor::computeOrigins( const FloatSize& innerSize, IntPoint& mainFrameOffset, FloatPoint& visualViewportOffset) const { IntSize outerSize = layoutViewport().visibleContentRect().size(); // Compute the viewport origins in CSS pixels relative to the document. FloatSize absVisualViewportOffset = m_normalizedVisualViewportOffset; absVisualViewportOffset.scale(outerSize.width(), outerSize.height()); FloatPoint innerOrigin = getInnerOrigin(innerSize); FloatPoint outerOrigin = innerOrigin - absVisualViewportOffset; IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize); FloatRect innerRect = FloatRect(innerOrigin, innerSize); moveToEncloseRect(outerRect, innerRect); outerRect.setLocation(IntPoint( layoutViewport().clampScrollOffset(toIntSize(outerRect.location())))); moveIntoRect(innerRect, outerRect); mainFrameOffset = outerRect.location(); visualViewportOffset = FloatPoint(innerRect.location() - outerRect.location()); }
FloatPoint RotationViewportAnchor::getInnerOrigin( const FloatSize& innerSize) const { if (!m_anchorNode || !m_anchorNode->isConnected()) return m_visualViewportInDocument; const LayoutRect currentNodeBounds = m_anchorNode->boundingBox(); if (m_anchorNodeBounds == currentNodeBounds) return m_visualViewportInDocument; RootFrameViewport* rootFrameViewport = m_rootFrameView->getRootFrameViewport(); const LayoutRect currentNodeBoundsInLayoutViewport = rootFrameViewport->rootContentsToLayoutViewportContents( *m_rootFrameView.get(), currentNodeBounds); // Compute the new anchor point relative to the node position FloatSize anchorOffsetFromNode(currentNodeBoundsInLayoutViewport.size()); anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(), m_anchorInNodeCoords.height()); FloatPoint anchorPoint = FloatPoint(currentNodeBoundsInLayoutViewport.location()) + anchorOffsetFromNode; // Compute the new origin point relative to the new anchor point FloatSize anchorOffsetFromOrigin = innerSize; anchorOffsetFromOrigin.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height()); return anchorPoint - anchorOffsetFromOrigin; }
// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the // point of intersection if they do and false otherwise. static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPoint& c, const FloatPoint& d, FloatPoint& r) { FloatSize u = b - a; FloatSize v = d - c; FloatSize w = a - c; float denom = perpProduct(u, v); // If denom == 0 then the edges are parallel. While they could be overlapping // we don't bother to check here as the we'll find their intersections from the // corner to quad tests. if (!denom) return false; float s = perpProduct(v, w) / denom; if (s < 0 || s > 1) return false; float t = perpProduct(u, w) / denom; if (t < 0 || t > 1) return false; u.scale(s); r = a + u; return true; }
int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSizeInPixels) { // Make sure the element is not freed during the layout. RefPtrWillBeRawPtr<Element> protect(element); element->document().updateLayout(); RenderBoxModelObject* box = enclosingBoxModelObject(element->renderer()); if (!box) return -1; LocalFrame* frame = element->document().frame(); FloatRect pageRect(FloatPoint(0, 0), pageSizeInPixels); PrintContext printContext(frame); printContext.begin(pageRect.width(), pageRect.height()); FloatSize scaledPageSize = pageSizeInPixels; scaledPageSize.scale(frame->view()->contentsSize().width() / pageRect.width()); printContext.computePageRectsWithPageSize(scaledPageSize, false); int top = box->pixelSnappedOffsetTop(); int left = box->pixelSnappedOffsetLeft(); size_t pageNumber = 0; for (; pageNumber < printContext.pageCount(); pageNumber++) { const IntRect& page = printContext.pageRect(pageNumber); if (page.x() <= left && left < page.maxX() && page.y() <= top && top < page.maxY()) return pageNumber; } return -1; }
static FloatSize convertToUserSpace(const FloatSize& deviceSize, float devicePixelRatio) { FloatSize result = deviceSize; if (devicePixelRatio != 1) result.scale(1 / devicePixelRatio); return result; }
IntSize CCPageScaleAnimation::scrollOffsetAtRatio(float ratio) const { if (ratio <= 0) return m_scrollStart; if (ratio >= 1) return m_scrollEnd; float currentPageScale = pageScaleAtRatio(ratio); IntSize currentScrollOffset; if (m_anchorMode) { // Keep the anchor stable on the screen at the current scale. IntSize documentAnchor = m_scrollStart + m_anchor; documentAnchor.scale(currentPageScale / m_pageScaleStart); currentScrollOffset = documentAnchor - m_anchor; } else { // First move both scroll offsets to the current coordinate space. FloatSize scaledStartScroll(m_scrollStart); scaledStartScroll.scale(currentPageScale / m_pageScaleStart); FloatSize scaledEndScroll(m_scrollEnd); scaledEndScroll.scale(currentPageScale / m_pageScaleEnd); // Linearly interpolate between them. FloatSize delta = scaledEndScroll - scaledStartScroll; delta.scale(ratio); currentScrollOffset = roundedIntSize(scaledStartScroll + delta); } return currentScrollOffset; }
inline IntSize EwkView::size() const { // WebPage expects a size in UI units, and not raw device units. FloatSize uiSize = deviceSize(); uiSize.scale(1 / deviceScaleFactor()); return roundedIntSize(uiSize); }
int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSizeInPixels) { element->document().updateStyleAndLayout(); LocalFrame* frame = element->document().frame(); FloatRect pageRect(FloatPoint(0, 0), pageSizeInPixels); PrintContext printContext(frame); printContext.begin(pageRect.width(), pageRect.height()); LayoutBoxModelObject* box = enclosingBoxModelObject(element->layoutObject()); if (!box) return -1; FloatSize scaledPageSize = pageSizeInPixels; scaledPageSize.scale(frame->view()->contentsSize().width() / pageRect.width()); printContext.computePageRectsWithPageSize(scaledPageSize); int top = box->pixelSnappedOffsetTop(box->offsetParent()); int left = box->pixelSnappedOffsetLeft(box->offsetParent()); size_t pageNumber = 0; for (; pageNumber < printContext.pageCount(); pageNumber++) { const IntRect& page = printContext.pageRect(pageNumber); if (page.x() <= left && left < page.maxX() && page.y() <= top && top < page.maxY()) return pageNumber; } return -1; }
void FullscreenVideoController::LayerClient::platformCALayerLayoutSublayersOfLayer(PlatformCALayer* layer) { ASSERT_ARG(layer, layer == m_parent->m_rootChild); HTMLVideoElement* videoElement = m_parent->m_videoElement.get(); if (!videoElement) return; PlatformCALayer* videoLayer = PlatformCALayer::platformCALayer(videoElement->platformLayer()); if (!videoLayer || videoLayer->superlayer() != layer) return; FloatRect layerBounds = layer->bounds(); FloatSize videoSize = videoElement->player()->naturalSize(); float scaleFactor; if (videoSize.aspectRatio() > layerBounds.size().aspectRatio()) scaleFactor = layerBounds.width() / videoSize.width(); else scaleFactor = layerBounds.height() / videoSize.height(); videoSize.scale(scaleFactor); // Calculate the centered position based on the videoBounds and layerBounds: FloatPoint videoPosition; FloatPoint videoOrigin; videoOrigin.setX((layerBounds.width() - videoSize.width()) * 0.5); videoOrigin.setY((layerBounds.height() - videoSize.height()) * 0.5); videoLayer->setPosition(videoOrigin); videoLayer->setBounds(FloatRect(FloatPoint(), videoSize)); }
void ViewportAnchor::setAnchor(const IntRect& viewRect, const FloatSize& anchorInViewCoords) { m_viewRect = viewRect; m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_anchorInViewCoords = anchorInViewCoords; if (viewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (viewRect.location() == IntPoint::zero()) return; FloatSize anchorOffset = viewRect.size(); anchorOffset.scale(anchorInViewCoords.width(), anchorInViewCoords.height()); const FloatPoint anchorPoint = FloatPoint(viewRect.location()) + anchorOffset; Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), viewRect, m_eventHandler); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPoint - m_anchorNodeBounds.location(); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode blendMode) { if (!m_page) return; ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(0); IntSize roundedContainerSize = roundedIntSize(containerSize); setContainerSize(roundedContainerSize); FloatRect scaledSrc = srcRect; scaledSrc.scale(1 / zoom); // Compensate for the container size rounding by adjusting the source rect. FloatSize adjustedSrcSize = scaledSrc.size(); adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); scaledSrc.setSize(adjustedSrcSize); draw(context, dstRect, scaledSrc, colorSpace, compositeOp, blendMode); setImageObserver(observer); }
void PageViewportControllerClientEfl::updateViewportSize() { ASSERT(m_controller); FloatSize size = m_view->size(); // The viewport controller expects sizes in UI units, and not raw device units. size.scale(1 / m_controller->deviceScaleFactor()); m_controller->didChangeViewportSize(size); }
IntPoint ViewportAnchor::computeOrigin(const IntSize& currentViewSize) const { if (!m_anchorNode || !m_anchorNode->inDocument()) return m_viewRect.location(); const LayoutRect currentNodeBounds = m_anchorNode->boundingBox(); if (m_anchorNodeBounds == currentNodeBounds) return m_viewRect.location(); // Compute the new anchor point relative to the node position FloatSize anchorOffsetFromNode = currentNodeBounds.size(); anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(), m_anchorInNodeCoords.height()); FloatPoint anchorPoint = currentNodeBounds.location() + anchorOffsetFromNode; // Compute the new origin point relative to the new anchor point FloatSize anchorOffsetFromOrigin = currentViewSize; anchorOffsetFromOrigin.scale(m_anchorInViewCoords.width(), m_anchorInViewCoords.height()); return flooredIntPoint(anchorPoint - anchorOffsetFromOrigin); }
IntPoint FrameView::clampOffsetAtScale(const IntPoint& offset, float scale) const { FloatSize scaledSize = unscaledVisibleContentSize(); if (scale) scaledSize.scale(1 / scale); IntPoint clampedOffset = offset; clampedOffset = clampedOffset.shrunkTo( IntPoint(size()) - expandedIntSize(scaledSize)); return clampedOffset; }
bool ImageBuffer::sizeNeedsClamping(const FloatSize& size, FloatSize& scale) { FloatSize scaledSize(size); scaledSize.scale(scale.width(), scale.height()); if (!sizeNeedsClamping(scaledSize)) return false; // The area of scaled size is bigger than the upper limit, adjust the scale to fit. scale.scale(sqrtf(MaxClampedArea / (scaledSize.width() * scaledSize.height()))); ASSERT(!sizeNeedsClamping(size, scale)); return true; }
int PrintContext::numberOfPages(LocalFrame* frame, const FloatSize& pageSizeInPixels) { frame->document()->updateLayout(); FloatRect pageRect(FloatPoint(0, 0), pageSizeInPixels); PrintContext printContext(frame); printContext.begin(pageRect.width(), pageRect.height()); // Account for shrink-to-fit. FloatSize scaledPageSize = pageSizeInPixels; scaledPageSize.scale(frame->view()->contentsSize().width() / pageRect.width()); printContext.computePageRectsWithPageSize(scaledPageSize, false); return printContext.pageCount(); }
bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale) { FloatSize scaledSize(size); scaledSize.scale(scale.width(), scale.height()); float scaledArea = scaledSize.width() * scaledSize.height(); if (scaledArea <= FilterEffect::maxFilterArea()) return true; // If area of scaled size is bigger than the upper limit, adjust the scale // to fit. scale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea)); return false; }
bool PrintContext::beginAndComputePageRectsWithPageSize(Frame& frame, const FloatSize& pageSizeInPixels) { if (!frame.document() || !frame.view() || !frame.document()->renderView()) return false; frame.document()->updateLayout(); begin(pageSizeInPixels.width(), pageSizeInPixels.height()); // Account for shrink-to-fit. FloatSize scaledPageSize = pageSizeInPixels; scaledPageSize.scale(frame.view()->contentsSize().width() / pageSizeInPixels.width()); computePageRectsWithPageSize(scaledPageSize, false); return true; }
void CCLayerTreeHostImpl::updateMaxScrollPosition() { if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size()) return; FloatSize viewBounds = m_viewportSize; viewBounds.scale(1 / m_pageScaleDelta); IntSize maxScroll = contentSize() - expandedIntSize(viewBounds); // The viewport may be larger than the contents in some cases, such as // having a vertical scrollbar but no horizontal overflow. maxScroll.clampNegativeToZero(); m_scrollLayerImpl->setMaxScrollPosition(maxScroll); // TODO(aelias): Also update sublayers. }
IntSize RenderImage::imageSizeForError(CachedImage* newImage) const { ASSERT_ARG(newImage, newImage); ASSERT_ARG(newImage, newImage->imageForRenderer(this)); FloatSize imageSize; if (newImage->willPaintBrokenImage()) { std::pair<Image*, float> brokenImageAndImageScaleFactor = newImage->brokenImage(document().deviceScaleFactor()); imageSize = brokenImageAndImageScaleFactor.first->size(); imageSize.scale(1 / brokenImageAndImageScaleFactor.second); } else imageSize = newImage->imageForRenderer(this)->size(); // imageSize() returns 0 for the error image. We need the true size of the // error image, so we have to get it by grabbing image() directly. return IntSize(paddingWidth + imageSize.width() * style().effectiveZoom(), paddingHeight + imageSize.height() * style().effectiveZoom()); }
// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the // point of intersection if they do and false otherwise. static bool edgeEdgeTest(const FloatPoint& a, const FloatPoint& b, const FloatPoint& c, const FloatPoint& d, FloatPoint& r) { FloatSize u = b - a; FloatSize v = d - c; FloatSize w = a - c; float denom = perpProduct(u, v); // If denom == 0 then the edges are parallel. if (!denom) { // If the edges are not colinear then there's no intersection. if (perpProduct(u, w) || perpProduct(v, w)) return false; if (pointInColinearEdge(a, c, d)) { r = a; return true; } if (pointInColinearEdge(b, c, d)) { r = b; return true; } if (pointInColinearEdge(c, a, b)) { r = c; return true; } if (pointInColinearEdge(d, a, b)) { r = d; return true; } return false; } float s = perpProduct(v, w) / denom; if (s < 0 || s > 1) return false; float t = perpProduct(u, w) / denom; if (t < 0 || t > 1) return false; u.scale(s); r = a + u; return true; }
FloatPoint ViewportAnchor::getInnerOrigin(const FloatSize& innerSize) const { if (!m_anchorNode || !m_anchorNode->inDocument()) return m_pinchViewportInDocument; const LayoutRect currentNodeBounds = m_anchorNode->boundingBox(); if (m_anchorNodeBounds == currentNodeBounds) return m_pinchViewportInDocument; // Compute the new anchor point relative to the node position FloatSize anchorOffsetFromNode(currentNodeBounds.size()); anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(), m_anchorInNodeCoords.height()); FloatPoint anchorPoint = FloatPoint(currentNodeBounds.location()) + anchorOffsetFromNode; // Compute the new origin point relative to the new anchor point FloatSize anchorOffsetFromOrigin = innerSize; anchorOffsetFromOrigin.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height()); return anchorPoint - anchorOffsetFromOrigin; }
SVGTransform* SVGTransformDistance::addSVGTransforms(SVGTransform* first, SVGTransform* second, unsigned repeatCount) { ASSERT(first->transformType() == second->transformType()); SVGTransform* transform = SVGTransform::create(); switch (first->transformType()) { case kSvgTransformMatrix: ASSERT_NOT_REACHED(); case kSvgTransformUnknown: return transform; case kSvgTransformRotate: { transform->setRotate(first->angle() + second->angle() * repeatCount, first->rotationCenter().x() + second->rotationCenter().x() * repeatCount, first->rotationCenter().y() + second->rotationCenter().y() * repeatCount); return transform; } case kSvgTransformTranslate: { float dx = first->translate().x() + second->translate().x() * repeatCount; float dy = first->translate().y() + second->translate().y() * repeatCount; transform->setTranslate(dx, dy); return transform; } case kSvgTransformScale: { FloatSize scale = second->scale(); scale.scale(repeatCount); scale += first->scale(); transform->setScale(scale.width(), scale.height()); return transform; } case kSvgTransformSkewx: transform->setSkewX(first->angle() + second->angle() * repeatCount); return transform; case kSvgTransformSkewy: transform->setSkewY(first->angle() + second->angle() * repeatCount); return transform; } ASSERT_NOT_REACHED(); return transform; }
void ViewportAnchor::setAnchor(const IntRect& outerViewRect, const IntRect& innerViewRect, const FloatSize& anchorInInnerViewCoords) { // Preserve the inner viewport position in document in case we won't find the anchor m_pinchViewportInDocument = innerViewRect.location(); m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_anchorInInnerViewCoords = anchorInInnerViewCoords; m_normalizedPinchViewportOffset = FloatSize(); if (innerViewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (innerViewRect.location() == IntPoint::zero()) return; // Inner rectangle should be within the outer one. ASSERT(outerViewRect.contains(innerViewRect)); // Outer rectangle is used as a scale, we need positive width and height. ASSERT(!outerViewRect.isEmpty()); m_normalizedPinchViewportOffset = innerViewRect.location() - outerViewRect.location(); // Normalize by the size of the outer rect m_normalizedPinchViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height()); FloatSize anchorOffset = innerViewRect.size(); anchorOffset.scale(anchorInInnerViewCoords.width(), anchorInInnerViewCoords.height()); const FloatPoint anchorPoint = FloatPoint(innerViewRect.location()) + anchorOffset; Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), innerViewRect, m_eventHandler); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPoint - FloatPoint(m_anchorNodeBounds.location()); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
PassRefPtr<SVGTransform> SVGTransformDistance::addSVGTransforms(PassRefPtr<SVGTransform> passFirst, PassRefPtr<SVGTransform> passSecond, unsigned repeatCount) { RefPtr<SVGTransform> first = passFirst; RefPtr<SVGTransform> second = passSecond; ASSERT(first->transformType() == second->transformType()); RefPtr<SVGTransform> transform = SVGTransform::create(); switch (first->transformType()) { case SVG_TRANSFORM_MATRIX: ASSERT_NOT_REACHED(); case SVG_TRANSFORM_UNKNOWN: return transform.release(); case SVG_TRANSFORM_ROTATE: { transform->setRotate(first->angle() + second->angle() * repeatCount, first->rotationCenter().x() + second->rotationCenter().x() * repeatCount, first->rotationCenter().y() + second->rotationCenter().y() * repeatCount); return transform.release(); } case SVG_TRANSFORM_TRANSLATE: { float dx = first->translate().x() + second->translate().x() * repeatCount; float dy = first->translate().y() + second->translate().y() * repeatCount; transform->setTranslate(dx, dy); return transform.release(); } case SVG_TRANSFORM_SCALE: { FloatSize scale = second->scale(); scale.scale(repeatCount); scale += first->scale(); transform->setScale(scale.width(), scale.height()); return transform.release(); } case SVG_TRANSFORM_SKEWX: transform->setSkewX(first->angle() + second->angle() * repeatCount); return transform.release(); case SVG_TRANSFORM_SKEWY: transform->setSkewY(first->angle() + second->angle() * repeatCount); return transform.release(); } ASSERT_NOT_REACHED(); return transform.release(); }
void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, blink::WebBlendMode blendMode) { if (!m_page) return; // Temporarily disable the image observer to prevent changeInRect() calls due re-laying out the image. ImageObserverDisabler imageObserverDisabler(this); IntSize roundedContainerSize = roundedIntSize(containerSize); setContainerSize(roundedContainerSize); FloatRect scaledSrc = srcRect; scaledSrc.scale(1 / zoom); // Compensate for the container size rounding by adjusting the source rect. FloatSize adjustedSrcSize = scaledSrc.size(); adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); scaledSrc.setSize(adjustedSrcSize); draw(context, dstRect, scaledSrc, compositeOp, blendMode); }
void SVGImage::drawForContainer(SkCanvas* canvas, const SkPaint& paint, const FloatSize containerSize, float zoom, const FloatRect& dstRect, const FloatRect& srcRect, const KURL& url) { if (!m_page) return; // Temporarily disable the image observer to prevent changeInRect() calls due re-laying out the image. ImageObserverDisabler imageObserverDisabler(this); IntSize roundedContainerSize = roundedIntSize(containerSize); setContainerSize(roundedContainerSize); FloatRect scaledSrc = srcRect; scaledSrc.scale(1 / zoom); // Compensate for the container size rounding by adjusting the source rect. FloatSize adjustedSrcSize = scaledSrc.size(); adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); scaledSrc.setSize(adjustedSrcSize); drawInternal(canvas, paint, dstRect, scaledSrc, DoNotRespectImageOrientation, ClampImageToSourceRect, url); }
SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second, unsigned repeatCount) { ASSERT(first.type() == second.type()); SVGTransform transform; switch (first.type()) { case SVGTransform::SVG_TRANSFORM_MATRIX: ASSERT_NOT_REACHED(); case SVGTransform::SVG_TRANSFORM_UNKNOWN: return SVGTransform(); case SVGTransform::SVG_TRANSFORM_ROTATE: { transform.setRotate(first.angle() + second.angle() * repeatCount, first.rotationCenter().x() + second.rotationCenter().x() * repeatCount, first.rotationCenter().y() + second.rotationCenter().y() * repeatCount); return transform; } case SVGTransform::SVG_TRANSFORM_TRANSLATE: { float dx = first.translate().x() + second.translate().x() * repeatCount; float dy = first.translate().y() + second.translate().y() * repeatCount; transform.setTranslate(dx, dy); return transform; } case SVGTransform::SVG_TRANSFORM_SCALE: { FloatSize scale = second.scale(); scale.scale(repeatCount); scale += first.scale(); transform.setScale(scale.width(), scale.height()); return transform; } case SVGTransform::SVG_TRANSFORM_SKEWX: transform.setSkewX(first.angle() + second.angle() * repeatCount); return transform; case SVGTransform::SVG_TRANSFORM_SKEWY: transform.setSkewY(first.angle() + second.angle() * repeatCount); return transform; } ASSERT_NOT_REACHED(); return SVGTransform(); }