/* * Copyright (C) 2007, 2009, 2012-2020 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "DragImage.h" #if ENABLE(DRAG_SUPPORT) && PLATFORM(MAC) #import "BitmapImage.h" #import "ColorMac.h" #import "Element.h" #import "FloatRoundedRect.h" #import "FontCascade.h" #import "FontDescription.h" #import "FontSelector.h" #import "GraphicsContextCG.h" #import "Image.h" #import "LocalDefaultSystemAppearance.h" #import "Page.h" #import "StringTruncator.h" #import "TextIndicator.h" #import "WebKitNSImageExtras.h" #import #import #import #import #import #if !HAVE(URL_FORMATTING) SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(LinkPresentation) #endif namespace WebCore { IntSize dragImageSize(RetainPtr image) { return (IntSize)[image size]; } void deleteDragImage(RetainPtr) { // Since this is a RetainPtr, there's nothing additional we need to do to // delete it. It will be released when it falls out of scope. } RetainPtr scaleDragImage(RetainPtr image, FloatSize scale) { NSSize originalSize = [image size]; NSSize newSize = NSMakeSize((originalSize.width * scale.width()), (originalSize.height * scale.height())); newSize.width = roundf(newSize.width); newSize.height = roundf(newSize.height); ALLOW_DEPRECATED_DECLARATIONS_BEGIN [image setScalesWhenResized:YES]; ALLOW_DEPRECATED_DECLARATIONS_END [image setSize:newSize]; return image; } RetainPtr dissolveDragImageToFraction(RetainPtr image, float delta) { if (!image) return nil; RetainPtr dissolvedImage = adoptNS([[NSImage alloc] initWithSize:[image size]]); [dissolvedImage lockFocus]; [image drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, [image size].width, [image size].height) operation:NSCompositingOperationCopy fraction:delta]; [dissolvedImage unlockFocus]; return dissolvedImage; } RetainPtr createDragImageFromImage(Image* image, ImageOrientation orientation) { if (is(*image)) { BitmapImage& bitmapImage = downcast(*image); if (orientation == ImageOrientation::FromImage) orientation = bitmapImage.orientationForCurrentFrame(); if (orientation != ImageOrientation::None) { // Construct a correctly-rotated copy of the image to use as the drag image. FloatSize imageSize = image->size(orientation); RetainPtr rotatedDragImage = adoptNS([[NSImage alloc] initWithSize:(NSSize)(imageSize)]); [rotatedDragImage lockFocus]; // ImageOrientation uses top-left coordinates, need to flip to bottom-left, apply... CGAffineTransform transform = CGAffineTransformMakeTranslation(0, imageSize.height()); transform = CGAffineTransformScale(transform, 1, -1); transform = CGAffineTransformConcat(orientation.transformFromDefault(imageSize), transform); if (orientation.usesWidthAsHeight()) imageSize = imageSize.transposedSize(); // ...and flip back. transform = CGAffineTransformTranslate(transform, 0, imageSize.height()); transform = CGAffineTransformScale(transform, 1, -1); RetainPtr cocoaTransform = adoptNS([[NSAffineTransform alloc] init]); [cocoaTransform setTransformStruct:*(NSAffineTransformStruct*)&transform]; [cocoaTransform concat]; FloatRect imageRect(FloatPoint(), imageSize); [image->snapshotNSImage() drawInRect:imageRect fromRect:imageRect operation:NSCompositingOperationSourceOver fraction:1.0]; [rotatedDragImage unlockFocus]; return rotatedDragImage; } } FloatSize imageSize = image->size(); auto dragImage = image->snapshotNSImage(); [dragImage setSize:(NSSize)imageSize]; return dragImage; } RetainPtr createDragImageIconForCachedImageFilename(const String& filename) { RetainPtr extension; size_t dotIndex = filename.reverseFind('.'); if (dotIndex != notFound && dotIndex < (filename.length() - 1)) // require that a . exists after the first character and before the last extension = StringView(filename).substring(dotIndex + 1).createNSString(); else { // It might be worth doing a further lookup to pull the extension from the MIME type. extension = @""; } ALLOW_DEPRECATED_DECLARATIONS_BEGIN return [[NSWorkspace sharedWorkspace] iconForFileType:extension.get()]; ALLOW_DEPRECATED_DECLARATIONS_END } const CGFloat linkImagePadding = 10; const CGFloat linkImageDomainBaselineToTitleBaseline = 18; const CGFloat linkImageCornerRadius = 5; const CGFloat linkImageMaximumWidth = 400; const CGFloat linkImageFontSize = 11; const CFIndex linkImageTitleMaximumLineCount = 2; const int linkImageShadowRadius = 0; const int linkImageShadowOffsetY = 0; const int linkImageDragCornerOutsetX = 6 - linkImageShadowRadius; const int linkImageDragCornerOutsetY = 10 - linkImageShadowRadius + linkImageShadowOffsetY; IntPoint dragOffsetForLinkDragImage(DragImageRef dragImage) { IntSize size = dragImageSize(dragImage); return { linkImageDragCornerOutsetX, size.height() + linkImageDragCornerOutsetY }; } FloatPoint anchorPointForLinkDragImage(DragImageRef dragImage) { IntSize size = dragImageSize(dragImage); return { -static_cast(linkImageDragCornerOutsetX) / size.width(), -static_cast(linkImageDragCornerOutsetY) / size.height() }; } struct LinkImageLayout { LinkImageLayout(URL&, const String& title); struct Label { FloatPoint origin; RetainPtr frame; }; Vector