void Path::translate(const FloatSize& size) { QTransform matrix; matrix.translate(size.width(), size.height()); m_path = m_path * matrix; }
void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius) { moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y())); addLineTo(FloatPoint(rect.maxX() - topRightRadius.width(), rect.y())); if (topRightRadius.width() > 0 || topRightRadius.height() > 0) 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())); if (bottomRightRadius.width() > 0 || bottomRightRadius.height() > 0) 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())); if (bottomLeftRadius.width() > 0 || bottomLeftRadius.height() > 0) 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())); if (topLeftRadius.width() > 0 || topLeftRadius.height() > 0) 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(); }
float computeMinimumScaleFactorForContentContained(const ViewportAttributes& result, const IntSize& visibleViewport, const IntSize& contentsSize, float devicePixelRatio) { FloatSize viewportSize = convertToUserSpace(visibleViewport, devicePixelRatio); return max<float>(result.minimumScale, max(viewportSize.width() / contentsSize.width(), viewportSize.height() / contentsSize.height())); }
static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio) { return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width()); }
void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) { intrinsicRatio = size(); intrinsicWidth = Length(intrinsicRatio.width(), Fixed); intrinsicHeight = Length(intrinsicRatio.height(), Fixed); }
static PassOwnPtr<Shape> createEllipseShape(const FloatPoint& center, const FloatSize& radii) { ASSERT(radii.width() >= 0 && radii.height() >= 0); return adoptPtr(new RectangleShape(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii)); }
void PrintContext::computePageRectsWithPageSizeInternal(const FloatSize& pageSizeInPixels, bool allowInlineDirectionTiling) { if (!m_frame->document() || !m_frame->view() || !m_frame->document()->renderView()) return; RenderView* view = m_frame->document()->renderView(); IntRect docRect = view->documentRect(); int pageWidth = pageSizeInPixels.width(); int pageHeight = pageSizeInPixels.height(); bool isHorizontal = view->style()->isHorizontalWritingMode(); int docLogicalHeight = isHorizontal ? docRect.height() : docRect.width(); int pageLogicalHeight = isHorizontal ? pageHeight : pageWidth; int pageLogicalWidth = isHorizontal ? pageWidth : pageHeight; int inlineDirectionStart; int inlineDirectionEnd; int blockDirectionStart; int blockDirectionEnd; if (isHorizontal) { if (view->style()->isFlippedBlocksWritingMode()) { blockDirectionStart = docRect.maxY(); blockDirectionEnd = docRect.y(); } else { blockDirectionStart = docRect.y(); blockDirectionEnd = docRect.maxY(); } inlineDirectionStart = view->style()->isLeftToRightDirection() ? docRect.x() : docRect.maxX(); inlineDirectionEnd = view->style()->isLeftToRightDirection() ? docRect.maxX() : docRect.x(); } else { if (view->style()->isFlippedBlocksWritingMode()) { blockDirectionStart = docRect.maxX(); blockDirectionEnd = docRect.x(); } else { blockDirectionStart = docRect.x(); blockDirectionEnd = docRect.maxX(); } inlineDirectionStart = view->style()->isLeftToRightDirection() ? docRect.y() : docRect.maxY(); inlineDirectionEnd = view->style()->isLeftToRightDirection() ? docRect.maxY() : docRect.y(); } unsigned pageCount = ceilf((float)docLogicalHeight / pageLogicalHeight); for (unsigned i = 0; i < pageCount; ++i) { int pageLogicalTop = blockDirectionEnd > blockDirectionStart ? blockDirectionStart + i * pageLogicalHeight : blockDirectionStart - (i + 1) * pageLogicalHeight; if (allowInlineDirectionTiling) { for (int currentInlinePosition = inlineDirectionStart; inlineDirectionEnd > inlineDirectionStart ? currentInlinePosition < inlineDirectionEnd : currentInlinePosition > inlineDirectionEnd; currentInlinePosition += (inlineDirectionEnd > inlineDirectionStart ? pageLogicalWidth : -pageLogicalWidth)) { int pageLogicalLeft = inlineDirectionEnd > inlineDirectionStart ? currentInlinePosition : currentInlinePosition - pageLogicalWidth; IntRect pageRect(pageLogicalLeft, pageLogicalTop, pageLogicalWidth, pageLogicalHeight); if (!isHorizontal) pageRect = pageRect.transposedRect(); m_pageRects.append(pageRect); } } else { int pageLogicalLeft = inlineDirectionEnd > inlineDirectionStart ? inlineDirectionStart : inlineDirectionStart - pageLogicalWidth; IntRect pageRect(pageLogicalLeft, pageLogicalTop, pageLogicalWidth, pageLogicalHeight); if (!isHorizontal) pageRect = pageRect.transposedRect(); m_pageRects.append(pageRect); } } }
inline static float perpProduct(const FloatSize& u, const FloatSize& v) { return u.width() * v.height() - u.height() * v.width(); }
inline static float innerProduct(const FloatSize& u, const FloatSize& v) { return u.width() * v.width() + u.height() * v.height(); }
void Path::translate(const FloatSize& size) { AffineTransform transformation; transformation.translate(size.width(), size.height()); transform(transformation); }
static Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer, bool& created) { ASSERT(!features.dialog || request.frameName().isEmpty()); if (!request.frameName().isEmpty() && request.frameName() != "_blank" && policy == NavigationPolicyIgnore) { if (Frame* frame = lookupFrame->loader().findFrameForNavigation(request.frameName(), openerFrame->document())) { if (request.frameName() != "_self") frame->page()->focusController().setFocusedFrame(frame); created = false; return frame; } } // Sandboxed frames cannot open new auxiliary browsing contexts. if (openerFrame->document()->isSandboxed(SandboxPopups)) { // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. openerFrame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest().url().elidedString() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set."); return 0; } if (openerFrame->settings() && !openerFrame->settings()->supportsMultipleWindows()) { created = false; return openerFrame->tree().top(); } Page* oldPage = openerFrame->page(); if (!oldPage) return 0; Page* page = oldPage->chrome().client().createWindow(openerFrame, request, features, policy, shouldSendReferrer); if (!page) return 0; FrameHost* host = &page->frameHost(); Frame* frame = page->mainFrame(); frame->loader().forceSandboxFlags(openerFrame->document()->sandboxFlags()); if (request.frameName() != "_blank") frame->tree().setName(request.frameName()); host->chrome().setWindowFeatures(features); // 'x' and 'y' specify the location of the window, while 'width' and 'height' // specify the size of the viewport. We can only resize the window, so adjust // for the difference between the window size and the viewport size. FloatRect windowRect = host->chrome().windowRect(); FloatSize viewportSize = host->chrome().pageRect().size(); if (features.xSet) windowRect.setX(features.x); if (features.ySet) windowRect.setY(features.y); if (features.widthSet) windowRect.setWidth(features.width + (windowRect.width() - viewportSize.width())); if (features.heightSet) windowRect.setHeight(features.height + (windowRect.height() - viewportSize.height())); // Ensure non-NaN values, minimum size as well as being within valid screen area. FloatRect newWindowRect = DOMWindow::adjustWindowRect(frame, windowRect); host->chrome().setWindowRect(newWindowRect); host->chrome().show(policy); created = true; return frame; }
FloatSize HTMLCanvasElement::convertDeviceToLogical(const FloatSize& deviceSize) const { float width = ceilf(deviceSize.width() / m_deviceScaleFactor); float height = ceilf(deviceSize.height() / m_deviceScaleFactor); return FloatSize(width, height); }
FloatSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const { float width = ceilf(logicalSize.width() * m_deviceScaleFactor); float height = ceilf(logicalSize.height() * m_deviceScaleFactor); return FloatSize(width, height); }
static inline float determinant(const FloatSize& a, const FloatSize& b) { return a.width() * b.height() - a.height() * b.width(); }
PageScaleConstraints ViewportDescription::resolve(const FloatSize& initialViewportSize, Length legacyFallbackWidth) const { float resultWidth = ValueAuto; Length copyMaxWidth = maxWidth; Length copyMinWidth = minWidth; // In case the width (used for min- and max-width) is undefined. if (isLegacyViewportType() && maxWidth.isAuto()) { // The width viewport META property is translated into 'width' descriptors, setting // the 'min' value to 'extend-to-zoom' and the 'max' value to the intended length. // In case the UA-defines a min-width, use that as length. if (zoom == ViewportDescription::ValueAuto) { copyMinWidth = Length(ExtendToZoom); copyMaxWidth = legacyFallbackWidth; } else if (maxHeight.isAuto()) { copyMinWidth = Length(ExtendToZoom); copyMaxWidth = Length(ExtendToZoom); } } float resultMaxWidth = resolveViewportLength(copyMaxWidth, initialViewportSize, Horizontal); float resultMinWidth = resolveViewportLength(copyMinWidth, initialViewportSize, Horizontal); float resultHeight = ValueAuto; float resultMaxHeight = resolveViewportLength(maxHeight, initialViewportSize, Vertical); float resultMinHeight = resolveViewportLength(minHeight, initialViewportSize, Vertical); float resultZoom = zoom; float resultMinZoom = minZoom; float resultMaxZoom = maxZoom; bool resultUserZoom = userZoom; // 1. Resolve min-zoom and max-zoom values. if (resultMinZoom != ViewportDescription::ValueAuto && resultMaxZoom != ViewportDescription::ValueAuto) resultMaxZoom = std::max(resultMinZoom, resultMaxZoom); // 2. Constrain zoom value to the [min-zoom, max-zoom] range. if (resultZoom != ViewportDescription::ValueAuto) resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resultMaxZoom, resultZoom, std::min), std::max); float extendZoom = compareIgnoringAuto(resultZoom, resultMaxZoom, std::min); // 3. Resolve non-"auto" lengths to pixel lengths. if (extendZoom == ViewportDescription::ValueAuto) { if (resultMaxWidth == ViewportDescription::ValueExtendToZoom) resultMaxWidth = ViewportDescription::ValueAuto; if (resultMaxHeight == ViewportDescription::ValueExtendToZoom) resultMaxHeight = ViewportDescription::ValueAuto; if (resultMinWidth == ViewportDescription::ValueExtendToZoom) resultMinWidth = resultMaxWidth; if (resultMinHeight == ViewportDescription::ValueExtendToZoom) resultMinHeight = resultMaxHeight; } else { float extendWidth = initialViewportSize.width() / extendZoom; float extendHeight = initialViewportSize.height() / extendZoom; if (resultMaxWidth == ViewportDescription::ValueExtendToZoom) resultMaxWidth = extendWidth; if (resultMaxHeight == ViewportDescription::ValueExtendToZoom) resultMaxHeight = extendHeight; if (resultMinWidth == ViewportDescription::ValueExtendToZoom) resultMinWidth = compareIgnoringAuto(extendWidth, resultMaxWidth, std::max); if (resultMinHeight == ViewportDescription::ValueExtendToZoom) resultMinHeight = compareIgnoringAuto(extendHeight, resultMaxHeight, std::max); } // 4. Resolve initial width from min/max descriptors. if (resultMinWidth != ViewportDescription::ValueAuto || resultMaxWidth != ViewportDescription::ValueAuto) resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(resultMaxWidth, initialViewportSize.width(), std::min), std::max); // 5. Resolve initial height from min/max descriptors. if (resultMinHeight != ViewportDescription::ValueAuto || resultMaxHeight != ViewportDescription::ValueAuto) resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto(resultMaxHeight, initialViewportSize.height(), std::min), std::max); // 6-7. Resolve width value. if (resultWidth == ViewportDescription::ValueAuto) { if (resultHeight == ViewportDescription::ValueAuto || !initialViewportSize.height()) resultWidth = initialViewportSize.width(); else resultWidth = resultHeight * (initialViewportSize.width() / initialViewportSize.height()); } // 8. Resolve height value. if (resultHeight == ViewportDescription::ValueAuto) { if (!initialViewportSize.width()) resultHeight = initialViewportSize.height(); else resultHeight = resultWidth * initialViewportSize.height() / initialViewportSize.width(); } // Resolve initial-scale value. if (resultZoom == ViewportDescription::ValueAuto) { if (resultWidth != ViewportDescription::ValueAuto && resultWidth > 0) resultZoom = initialViewportSize.width() / resultWidth; if (resultHeight != ViewportDescription::ValueAuto && resultHeight > 0) { // if 'auto', the initial-scale will be negative here and thus ignored. resultZoom = std::max<float>(resultZoom, initialViewportSize.height() / resultHeight); } } // If user-scalable = no, lock the min/max scale to the computed initial // scale. if (!resultUserZoom) resultMinZoom = resultMaxZoom = resultZoom; // Only set initialScale to a value if it was explicitly set. if (zoom == ViewportDescription::ValueAuto) resultZoom = ViewportDescription::ValueAuto; PageScaleConstraints result; result.minimumScale = resultMinZoom; result.maximumScale = resultMaxZoom; result.initialScale = resultZoom; result.layoutSize.setWidth(resultWidth); result.layoutSize.setHeight(resultHeight); return result; }
ViewportAttributes ViewportArguments::resolve(const FloatSize& initialViewportSize, const FloatSize& deviceSize, int defaultWidth) const { float resultWidth = width; float resultMaxWidth = maxWidth; float resultMinWidth = minWidth; float resultHeight = height; float resultMinHeight = minHeight; float resultMaxHeight = maxHeight; float resultZoom = zoom; float resultMinZoom = minZoom; float resultMaxZoom = maxZoom; float resultUserZoom = userZoom; switch (int(resultWidth)) { case ViewportArguments::ValueDeviceWidth: resultWidth = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultWidth = deviceSize.height(); break; } switch (int(resultHeight)) { case ViewportArguments::ValueDeviceWidth: resultHeight = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultHeight = deviceSize.height(); break; } if (type == ViewportArguments::CSSDeviceAdaptation) { switch (int(resultMinWidth)) { case ViewportArguments::ValueDeviceWidth: resultMinWidth = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultMinWidth = deviceSize.height(); break; } switch (int(resultMaxWidth)) { case ViewportArguments::ValueDeviceWidth: resultMaxWidth = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultMaxWidth = deviceSize.height(); break; } switch (int(resultMinHeight)) { case ViewportArguments::ValueDeviceWidth: resultMinHeight = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultMinHeight = deviceSize.height(); break; } switch (int(resultMaxHeight)) { case ViewportArguments::ValueDeviceWidth: resultMaxHeight = deviceSize.width(); break; case ViewportArguments::ValueDeviceHeight: resultMaxHeight = deviceSize.height(); break; } if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != ViewportArguments::ValueAuto) resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(resultMaxWidth, deviceSize.width(), std::min), std::max); if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight != ViewportArguments::ValueAuto) resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto(resultMaxHeight, deviceSize.height(), std::min), std::max); if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != ViewportArguments::ValueAuto) resultMaxZoom = std::max(resultMinZoom, resultMaxZoom); if (resultZoom != ViewportArguments::ValueAuto) resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resultMaxZoom, resultZoom, std::min), std::max); if (resultWidth == ViewportArguments::ValueAuto && resultZoom == ViewportArguments::ValueAuto) resultWidth = deviceSize.width(); if (resultWidth == ViewportArguments::ValueAuto && resultHeight == ViewportArguments::ValueAuto) resultWidth = deviceSize.width() / resultZoom; if (resultWidth == ViewportArguments::ValueAuto) resultWidth = resultHeight * deviceSize.width() / deviceSize.height(); if (resultHeight == ViewportArguments::ValueAuto) resultHeight = resultWidth * deviceSize.height() / deviceSize.width(); if (resultZoom != ViewportArguments::ValueAuto || resultMaxZoom != ViewportArguments::ValueAuto) { resultWidth = compareIgnoringAuto(resultWidth, deviceSize.width() / compareIgnoringAuto(resultZoom, resultMaxZoom, std::min), std::max); resultHeight = compareIgnoringAuto(resultHeight, deviceSize.height() / compareIgnoringAuto(resultZoom, resultMaxZoom, std::min), std::max); } resultWidth = std::max<float>(1, resultWidth); resultHeight = std::max<float>(1, resultHeight); } if (type != ViewportArguments::CSSDeviceAdaptation && type != ViewportArguments::Implicit) { // Clamp values to a valid range, but not for @viewport since is // not mandated by the specification. resultWidth = clampLengthValue(resultWidth); resultHeight = clampLengthValue(resultHeight); resultZoom = clampScaleValue(resultZoom); resultMinZoom = clampScaleValue(resultMinZoom); resultMaxZoom = clampScaleValue(resultMaxZoom); } ViewportAttributes result; // Resolve minimum-scale and maximum-scale values according to spec. if (resultMinZoom == ViewportArguments::ValueAuto) result.minimumScale = float(0.25); else result.minimumScale = resultMinZoom; if (resultMaxZoom == ViewportArguments::ValueAuto) { result.maximumScale = 5; result.minimumScale = std::min<float>(5, result.minimumScale); } else result.maximumScale = resultMaxZoom; result.maximumScale = std::max(result.minimumScale, result.maximumScale); // Resolve initial-scale value. result.initialScale = resultZoom; if (resultZoom == ViewportArguments::ValueAuto) { result.initialScale = initialViewportSize.width() / defaultWidth; if (resultWidth != ViewportArguments::ValueAuto) result.initialScale = initialViewportSize.width() / resultWidth; if (resultHeight != ViewportArguments::ValueAuto) { // if 'auto', the initial-scale will be negative here and thus ignored. result.initialScale = std::max<float>(result.initialScale, initialViewportSize.height() / resultHeight); } } // Constrain initial-scale value to minimum-scale/maximum-scale range. result.initialScale = std::min(result.maximumScale, std::max(result.minimumScale, result.initialScale)); // Resolve width value. if (resultWidth == ViewportArguments::ValueAuto) { if (resultZoom == ViewportArguments::ValueAuto) resultWidth = defaultWidth; else if (resultHeight != ViewportArguments::ValueAuto) resultWidth = resultHeight * (initialViewportSize.width() / initialViewportSize.height()); else resultWidth = initialViewportSize.width() / result.initialScale; } // Resolve height value. if (resultHeight == ViewportArguments::ValueAuto) resultHeight = resultWidth * (initialViewportSize.height() / initialViewportSize.width()); if (type == ViewportArguments::ViewportMeta) { // Extend width and height to fill the visual viewport for the resolved initial-scale. resultWidth = std::max<float>(resultWidth, initialViewportSize.width() / result.initialScale); resultHeight = std::max<float>(resultHeight, initialViewportSize.height() / result.initialScale); } result.layoutSize.setWidth(resultWidth); result.layoutSize.setHeight(resultHeight); // FIXME: This might affect some ports, but is the right thing to do. // Only set initialScale to a value if it was explicitly set. // if (resultZoom == ViewportArguments::ValueAuto) // result.initialScale = ViewportArguments::ValueAuto; result.userScalable = resultUserZoom; result.orientation = orientation; return result; }
static PassOwnPtr<Shape> createRectangleShape(const FloatRect& bounds, const FloatSize& radii) { ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0); return adoptPtr(new RectangleShape(bounds, radii)); }
static std::unique_ptr<Shape> createEllipseShape(const FloatPoint& center, const FloatSize& radii) { ASSERT(radii.width() >= 0 && radii.height() >= 0); return std::make_unique<RectangleShape>(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii); }
static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode writingMode) { if (isHorizontalWritingMode(writingMode)) return size; return size.transposedSize(); }
void LayoutReplaced::computeAspectRatioInformationForLayoutBox(LayoutBox* contentLayoutObject, FloatSize& constrainedSize, double& intrinsicRatio) const { FloatSize intrinsicSize; if (contentLayoutObject) { contentLayoutObject->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio); // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them. intrinsicSize.scale(style()->effectiveZoom()); if (isLayoutImage()) intrinsicSize.scale(toLayoutImage(this)->imageDevicePixelRatio()); // Update our intrinsic size to match what the content layoutObject 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 && !intrinsicSize.isEmpty()) m_intrinsicSize = LayoutSize(intrinsicSize); if (!isHorizontalWritingMode()) { if (intrinsicRatio) intrinsicRatio = 1 / intrinsicRatio; intrinsicSize = intrinsicSize.transposedSize(); } } else { computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio); if (intrinsicRatio && !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 && !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(LayoutBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height()); constrainedSize.setHeight(LayoutBox::computeReplacedLogicalWidth() * intrinsicSize.height() / intrinsicSize.width()); } }
static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio) { return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height()); }
LayoutUnit LayoutReplaced::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const { if (style()->logicalWidth().isSpecified() || style()->logicalWidth().isIntrinsic()) return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(MainOrPreferredSize, style()->logicalWidth()), shouldComputePreferred); LayoutBox* contentLayoutObject = embeddedContentBox(); // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width double intrinsicRatio = 0; FloatSize constrainedSize; computeAspectRatioInformationForLayoutBox(contentLayoutObject, constrainedSize, intrinsicRatio); if (style()->logicalWidth().isAuto()) { bool computedHeightIsAuto = hasAutoHeightOrContainingBlockWithAutoHeight(); bool hasIntrinsicWidth = constrainedSize.width() > 0; // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'. if (computedHeightIsAuto && hasIntrinsicWidth) return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred); bool hasIntrinsicHeight = constrainedSize.height() > 0; if (intrinsicRatio) { // If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio; // or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value // of 'width' is: (used height) * (intrinsic ratio) if (intrinsicRatio && ((computedHeightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !computedHeightIsAuto)) { LayoutUnit logicalHeight = computeReplacedLogicalHeight(); return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalHeight * intrinsicRatio, shouldComputePreferred); } // If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then // the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow. if (computedHeightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) { if (shouldComputePreferred == ComputePreferred) return 0; // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow: // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth(); // This solves above equation for 'width' (== logicalWidth). LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth); LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth); logicalWidth = std::max<LayoutUnit>(0, logicalWidth - (marginStart + marginEnd + (size().width() - clientWidth()))); return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, shouldComputePreferred); } } // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'. if (hasIntrinsicWidth) return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred); // Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead. // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired. // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto) // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time. } return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), shouldComputePreferred); }
void Path::translate(const FloatSize& size) { m_path->offset(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op) { if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, destRect, solidColor(), op); return; } FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height()); FloatRect oneTileRect; oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width())); oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.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)) { 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); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPatternCounter.startCounting(); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect); drawPatternCounter.stopCounting(); startAnimation(); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, SkXfermode::Mode op, const IntSize& repeatSpacing) { FloatSize intrinsicTileSize = size(); if (hasRelativeWidth()) intrinsicTileSize.setWidth(scaledTileSize.width()); if (hasRelativeHeight()) intrinsicTileSize.setHeight(scaledTileSize.height()); FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), scaledTileSize.height() / intrinsicTileSize.height()); FloatSize actualTileSize(scaledTileSize.width() + repeatSpacing.width(), scaledTileSize.height() + repeatSpacing.height()); FloatRect oneTileRect; 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)) { 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()); ctxt->drawImage(this, destRect, visibleSrcRect, op, DoNotRespectImageOrientation); return; } FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, repeatSpacing); startAnimation(); }
FloatSize LocalFrame::resizePageRectsKeepingRatio( const FloatSize& originalSize, const FloatSize& expectedSize) { FloatSize resultSize; if (contentLayoutItem().isNull()) return FloatSize(); if (contentLayoutItem().style()->isHorizontalWritingMode()) { ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon()); float ratio = originalSize.height() / originalSize.width(); resultSize.setWidth(floorf(expectedSize.width())); resultSize.setHeight(floorf(resultSize.width() * ratio)); } else { ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon()); float ratio = originalSize.width() / originalSize.height(); resultSize.setHeight(floorf(expectedSize.height())); resultSize.setWidth(floorf(resultSize.height() * ratio)); } return resultSize; }
static inline float viewportMaxPercent(const FloatSize& viewportSize) { return std::max(viewportSize.width(), viewportSize.height()) / 100; }
static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) { if (platformContext->hasImageResamplingHint()) { IntSize srcSize; FloatSize dstSize; platformContext->getImageResamplingHint(&srcSize, &dstSize); srcWidth = srcSize.width(); srcHeight = srcSize.height(); destWidth = dstSize.width(); destHeight = dstSize.height(); } int destIWidth = static_cast<int>(destWidth); int destIHeight = static_cast<int>(destHeight); // The percent change below which we will not resample. This usually means // an off-by-one error on the web page, and just doing nearest neighbor // sampling is usually good enough. const float kFractionalChangeThreshold = 0.025f; // Images smaller than this in either direction are considered "small" and // are not resampled ever (see below). const int kSmallImageSizeThreshold = 8; // The amount an image can be stretched in a single direction before we // say that it is being stretched so much that it must be a line or // background that doesn't need resampling. const float kLargeStretch = 3.0f; // Figure out if we should resample this image. We try to prune out some // common cases where resampling won't give us anything, since it is much // slower than drawing stretched. if (srcWidth == destIWidth && srcHeight == destIHeight) { // We don't need to resample if the source and destination are the same. return RESAMPLE_NONE; } if (srcWidth <= kSmallImageSizeThreshold || srcHeight <= kSmallImageSizeThreshold || destWidth <= kSmallImageSizeThreshold || destHeight <= kSmallImageSizeThreshold) { // Never resample small images. These are often used for borders and // rules (think 1x1 images used to make lines). return RESAMPLE_NONE; } if (srcHeight * kLargeStretch <= destHeight || srcWidth * kLargeStretch <= destWidth) { // Large image detected. // Don't resample if it is being stretched a lot in only one direction. // This is trying to catch cases where somebody has created a border // (which might be large) and then is stretching it to fill some part // of the page. if (srcWidth == destWidth || srcHeight == destHeight) return RESAMPLE_NONE; // The image is growing a lot and in more than one direction. Resampling // is slow and doesn't give us very much when growing a lot. return RESAMPLE_LINEAR; } if ((fabs(destWidth - srcWidth) / srcWidth < kFractionalChangeThreshold) && (fabs(destHeight - srcHeight) / srcHeight < kFractionalChangeThreshold)) { // It is disappointingly common on the web for image sizes to be off by // one or two pixels. We don't bother resampling if the size difference // is a small fraction of the original size. return RESAMPLE_NONE; } // When the image is not yet done loading, use linear. We don't cache the // partially resampled images, and as they come in incrementally, it causes // us to have to resample the whole thing every time. if (!bitmap.isDataComplete()) return RESAMPLE_LINEAR; // Everything else gets resampled. // If the platform context permits high quality interpolation, use it. // High quality interpolation only enabled for scaling and translation. if (platformContext->interpolationQuality() == InterpolationHigh && !(platformContext->canvas()->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) return RESAMPLE_AWESOME; return RESAMPLE_LINEAR; }
void restrictMinimumScaleFactorToViewportSize(ViewportAttributes& result, IntSize visibleViewport, float devicePixelRatio) { FloatSize viewportSize = convertToUserSpace(visibleViewport, devicePixelRatio); result.minimumScale = max<float>(result.minimumScale, max(viewportSize.width() / result.layoutSize.width(), viewportSize.height() / result.layoutSize.height())); }
void SVGPreserveAspectRatio::transformRect(FloatRect& destRect, FloatRect& srcRect) { if (m_align == SVG_PRESERVEASPECTRATIO_NONE) return; FloatSize imageSize = srcRect.size(); float origDestWidth = destRect.width(); float origDestHeight = destRect.height(); switch (m_meetOrSlice) { case SVGPreserveAspectRatio::SVG_MEETORSLICE_UNKNOWN: break; case SVGPreserveAspectRatio::SVG_MEETORSLICE_MEET: { float widthToHeightMultiplier = srcRect.height() / srcRect.width(); if (origDestHeight > origDestWidth * widthToHeightMultiplier) { destRect.setHeight(origDestWidth * widthToHeightMultiplier); switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: destRect.setY(destRect.y() + origDestHeight / 2 - destRect.height() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: destRect.setY(destRect.y() + origDestHeight - destRect.height()); break; default: break; } } if (origDestWidth > origDestHeight / widthToHeightMultiplier) { destRect.setWidth(origDestHeight / widthToHeightMultiplier); switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: destRect.setX(destRect.x() + origDestWidth / 2 - destRect.width() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: destRect.setX(destRect.x() + origDestWidth - destRect.width()); break; default: break; } } break; } case SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE: { float widthToHeightMultiplier = srcRect.height() / srcRect.width(); // if the destination height is less than the height of the image we'll be drawing if (origDestHeight < origDestWidth * widthToHeightMultiplier) { float destToSrcMultiplier = srcRect.width() / destRect.width(); srcRect.setHeight(destRect.height() * destToSrcMultiplier); switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: srcRect.setY(srcRect.y() + imageSize.height() / 2 - srcRect.height() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: srcRect.setY(srcRect.y() + imageSize.height() - srcRect.height()); break; default: break; } } // if the destination width is less than the width of the image we'll be drawing if (origDestWidth < origDestHeight / widthToHeightMultiplier) { float destToSrcMultiplier = srcRect.height() / destRect.height(); srcRect.setWidth(destRect.width() * destToSrcMultiplier); switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: srcRect.setX(srcRect.x() + imageSize.width() / 2 - srcRect.width() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: srcRect.setX(srcRect.x() + imageSize.width() - srcRect.width()); break; default: break; } } break; } } }