summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/win/DragImageWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/win/DragImageWin.cpp')
-rw-r--r--Source/WebCore/platform/win/DragImageWin.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/Source/WebCore/platform/win/DragImageWin.cpp b/Source/WebCore/platform/win/DragImageWin.cpp
new file mode 100644
index 000000000..989a0b546
--- /dev/null
+++ b/Source/WebCore/platform/win/DragImageWin.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2007, 2008, 2013 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.
+ */
+
+#include "config.h"
+#include "DragImage.h"
+
+#include "FloatRoundedRect.h"
+#include "FontCascade.h"
+#include "FontDescription.h"
+#include "FontSelector.h"
+#include "GraphicsContext.h"
+#include "HWndDC.h"
+#include "Image.h"
+#include "URL.h"
+#include "StringTruncator.h"
+#include "TextRun.h"
+#include "WebCoreTextRenderer.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/win/GDIObject.h>
+
+#include <windows.h>
+
+namespace WebCore {
+
+GDIObject<HBITMAP> allocImage(HDC, IntSize, PlatformGraphicsContext** targetRef);
+void deallocContext(PlatformGraphicsContext* target);
+
+IntSize dragImageSize(DragImageRef image)
+{
+ if (!image)
+ return IntSize();
+ BITMAP b;
+ GetObject(image, sizeof(BITMAP), &b);
+ return IntSize(b.bmWidth, b.bmHeight);
+}
+
+void deleteDragImage(DragImageRef image)
+{
+ if (image)
+ ::DeleteObject(image);
+}
+
+DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
+{
+ //We don't do this on windows as the dragimage is blended by the OS
+ return image;
+}
+
+DragImageRef createDragImageIconForCachedImageFilename(const String& filename)
+{
+ SHFILEINFO shfi = {0};
+ String fname = filename;
+ if (FAILED(SHGetFileInfo(static_cast<LPCWSTR>(fname.charactersWithNullTermination().data()), FILE_ATTRIBUTE_NORMAL,
+ &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES)))
+ return 0;
+
+ ICONINFO iconInfo;
+ if (!GetIconInfo(shfi.hIcon, &iconInfo)) {
+ DestroyIcon(shfi.hIcon);
+ return 0;
+ }
+
+ DestroyIcon(shfi.hIcon);
+ DeleteObject(iconInfo.hbmMask);
+
+ return iconInfo.hbmColor;
+}
+
+const float DragLabelBorderX = 4;
+// Keep border_y in synch with DragController::LinkDragBorderInset.
+const float DragLabelBorderY = 2;
+const float DragLabelRadius = 5;
+const float LabelBorderYOffset = 2;
+
+const float MinDragLabelWidthBeforeClip = 120;
+const float MaxDragLabelWidth = 200;
+const float MaxDragLabelStringWidth = (MaxDragLabelWidth - 2 * DragLabelBorderX);
+
+const float DragLinkLabelFontsize = 11;
+const float DragLinkUrlFontSize = 10;
+
+static FontCascade dragLabelFont(int size, bool bold, FontRenderingMode renderingMode)
+{
+ FontCascade result;
+ NONCLIENTMETRICS metrics;
+ metrics.cbSize = sizeof(metrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
+
+ FontCascadeDescription description;
+ description.setWeight(bold ? FontWeightBold : FontWeightNormal);
+ description.setOneFamily(metrics.lfSmCaptionFont.lfFaceName);
+ description.setSpecifiedSize((float)size);
+ description.setComputedSize((float)size);
+ description.setRenderingMode(renderingMode);
+ result = FontCascade(description, 0, 0);
+ result.update(0);
+ return result;
+}
+
+DragImageRef createDragImageForLink(URL& url, const String& inLabel, FontRenderingMode fontRenderingMode)
+{
+ // This is more or less an exact match for the Mac OS X code.
+
+ const FontCascade* labelFont;
+ const FontCascade* urlFont;
+
+ if (fontRenderingMode == FontRenderingMode::Alternate) {
+ static const FontCascade alternateRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, FontRenderingMode::Alternate);
+ static const FontCascade alternateRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, FontRenderingMode::Alternate);
+ labelFont = &alternateRenderingModeLabelFont;
+ urlFont = &alternateRenderingModeURLFont;
+ } else {
+ static const FontCascade normalRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, FontRenderingMode::Normal);
+ static const FontCascade normalRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, FontRenderingMode::Normal);
+ labelFont = &normalRenderingModeLabelFont;
+ urlFont = &normalRenderingModeURLFont;
+ }
+
+ bool drawURLString = true;
+ bool clipURLString = false;
+ bool clipLabelString = false;
+
+ String urlString = url.string();
+ String label = inLabel;
+ if (label.isEmpty()) {
+ drawURLString = false;
+ label = urlString;
+ }
+
+ // First step in drawing the link drag image width.
+ TextRun labelRun(label);
+ TextRun urlRun(urlString);
+ IntSize labelSize(labelFont->width(labelRun), labelFont->fontMetrics().ascent() + labelFont->fontMetrics().descent());
+
+ if (labelSize.width() > MaxDragLabelStringWidth) {
+ labelSize.setWidth(MaxDragLabelStringWidth);
+ clipLabelString = true;
+ }
+
+ IntSize urlStringSize;
+ IntSize imageSize(labelSize.width() + DragLabelBorderX * 2, labelSize.height() + DragLabelBorderY * 2);
+
+ if (drawURLString) {
+ urlStringSize.setWidth(urlFont->width(urlRun));
+ urlStringSize.setHeight(urlFont->fontMetrics().ascent() + urlFont->fontMetrics().descent());
+ imageSize.setHeight(imageSize.height() + urlStringSize.height());
+ if (urlStringSize.width() > MaxDragLabelStringWidth) {
+ imageSize.setWidth(MaxDragLabelWidth);
+ clipURLString = true;
+ } else
+ imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DragLabelBorderX * 2);
+ }
+
+ // We now know how big the image needs to be, so we create and
+ // fill the background
+ HWndDC dc(0);
+ auto workingDC = adoptGDIObject(::CreateCompatibleDC(dc));
+ if (!workingDC)
+ return 0;
+
+ PlatformGraphicsContext* contextRef;
+ auto image = allocImage(workingDC.get(), imageSize, &contextRef);
+ if (!image)
+ return 0;
+
+ ::SelectObject(workingDC.get(), image.get());
+ GraphicsContext context(contextRef);
+ // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha
+ // for drag images on win, so we use 1
+ static const Color backgroundColor(140, 140, 140);
+ static const IntSize radii(DragLabelRadius, DragLabelRadius);
+ IntRect rect(0, 0, imageSize.width(), imageSize.height());
+ context.fillRoundedRect(FloatRoundedRect(rect, radii, radii, radii, radii), backgroundColor);
+
+ // Draw the text
+ static const Color topColor(0, 0, 0, 255); // original alpha = 0.75
+ static const Color bottomColor(255, 255, 255, 127); // original alpha = 0.5
+ if (drawURLString) {
+ if (clipURLString)
+ urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DragLabelBorderX * 2.0f), *urlFont);
+ IntPoint textPos(DragLabelBorderX, imageSize.height() - (LabelBorderYOffset + urlFont->fontMetrics().descent()));
+ WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, topColor, bottomColor);
+ }
+
+ if (clipLabelString)
+ label = StringTruncator::rightTruncate(label, imageSize.width() - (DragLabelBorderX * 2.0f), *labelFont);
+
+ IntPoint textPos(DragLabelBorderX, DragLabelBorderY + labelFont->pixelSize());
+ WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor, bottomColor);
+
+ deallocContext(contextRef);
+ return image.leak();
+}
+
+}