Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "DragImage.h"
     28 
     29 #include "CachedImage.h"
     30 #include "Font.h"
     31 #include "FontDescription.h"
     32 #include "FontSelector.h"
     33 #include "Frame.h"
     34 #include "GraphicsContext.h"
     35 #include "Image.h"
     36 #include "RetainPtr.h"
     37 #include "Settings.h"
     38 #include "StringTruncator.h"
     39 #include "TextRun.h"
     40 #include "WebCoreTextRenderer.h"
     41 
     42 #include <windows.h>
     43 
     44 namespace WebCore {
     45 
     46 HBITMAP allocImage(HDC, IntSize, PlatformGraphicsContext** targetRef);
     47 void deallocContext(PlatformGraphicsContext* target);
     48 
     49 IntSize dragImageSize(DragImageRef image)
     50 {
     51     if (!image)
     52         return IntSize();
     53     BITMAP b;
     54     GetObject(image, sizeof(BITMAP), &b);
     55     return IntSize(b.bmWidth, b.bmHeight);
     56 }
     57 
     58 void deleteDragImage(DragImageRef image)
     59 {
     60     if (image)
     61         ::DeleteObject(image);
     62 }
     63 
     64 DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
     65 {
     66     //We don't do this on windows as the dragimage is blended by the OS
     67     return image;
     68 }
     69 
     70 DragImageRef createDragImageIconForCachedImage(CachedImage* image)
     71 {
     72     if (!image)
     73         return 0;
     74 
     75     String filename = image->response().suggestedFilename();
     76 
     77     SHFILEINFO shfi = {0};
     78     if (FAILED(SHGetFileInfo(static_cast<LPCWSTR>(filename.charactersWithNullTermination()), FILE_ATTRIBUTE_NORMAL,
     79         &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES)))
     80         return 0;
     81 
     82     ICONINFO iconInfo;
     83     if (!GetIconInfo(shfi.hIcon, &iconInfo)) {
     84         DestroyIcon(shfi.hIcon);
     85         return 0;
     86     }
     87 
     88     DestroyIcon(shfi.hIcon);
     89     DeleteObject(iconInfo.hbmMask);
     90 
     91     return iconInfo.hbmColor;
     92 }
     93 
     94 const float DragLabelBorderX = 4;
     95 // Keep border_y in synch with DragController::LinkDragBorderInset.
     96 const float DragLabelBorderY = 2;
     97 const float DragLabelRadius = 5;
     98 const float LabelBorderYOffset = 2;
     99 
    100 const float MinDragLabelWidthBeforeClip = 120;
    101 const float MaxDragLabelWidth = 200;
    102 const float MaxDragLabelStringWidth = (MaxDragLabelWidth - 2 * DragLabelBorderX);
    103 
    104 const float DragLinkLabelFontsize = 11;
    105 const float DragLinkUrlFontSize = 10;
    106 
    107 static Font dragLabelFont(int size, bool bold, FontRenderingMode renderingMode)
    108 {
    109     NONCLIENTMETRICS metrics;
    110     metrics.cbSize = sizeof(metrics);
    111     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
    112 
    113     FontDescription description;
    114     description.setWeight(bold ? FontWeightBold : FontWeightNormal);
    115 
    116     FontFamily family;
    117     family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
    118     description.setFamily(family);
    119     description.setSpecifiedSize((float)size);
    120     description.setComputedSize((float)size);
    121     description.setRenderingMode(renderingMode);
    122     Font result = Font(description, 0, 0);
    123     result.update(0);
    124     return result;
    125 }
    126 
    127 DragImageRef createDragImageForLink(KURL& url, const String& inLabel, Frame* frame)
    128 {
    129     // This is more or less an exact match for the Mac OS X code.
    130 
    131     const Font* labelFont;
    132     const Font* urlFont;
    133 
    134     if (frame->settings() && frame->settings()->fontRenderingMode() == AlternateRenderingMode) {
    135         static const Font alternateRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, AlternateRenderingMode);
    136         static const Font alternateRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, AlternateRenderingMode);
    137         labelFont = &alternateRenderingModeLabelFont;
    138         urlFont = &alternateRenderingModeURLFont;
    139     } else {
    140         static const Font normalRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, NormalRenderingMode);
    141         static const Font normalRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, NormalRenderingMode);
    142         labelFont = &normalRenderingModeLabelFont;
    143         urlFont = &normalRenderingModeURLFont;
    144     }
    145 
    146     bool drawURLString = true;
    147     bool clipURLString = false;
    148     bool clipLabelString = false;
    149 
    150     String urlString = url.string();
    151     String label = inLabel;
    152     if (label.isEmpty()) {
    153         drawURLString = false;
    154         label = urlString;
    155     }
    156 
    157     // First step in drawing the link drag image width.
    158     TextRun labelRun(label.impl());
    159     TextRun urlRun(urlString.impl());
    160     IntSize labelSize(labelFont->width(labelRun), labelFont->fontMetrics().ascent() + labelFont->fontMetrics().descent());
    161 
    162     if (labelSize.width() > MaxDragLabelStringWidth) {
    163         labelSize.setWidth(MaxDragLabelStringWidth);
    164         clipLabelString = true;
    165     }
    166 
    167     IntSize urlStringSize;
    168     IntSize imageSize(labelSize.width() + DragLabelBorderX * 2, labelSize.height() + DragLabelBorderY * 2);
    169 
    170     if (drawURLString) {
    171         urlStringSize.setWidth(urlFont->width(urlRun));
    172         urlStringSize.setHeight(urlFont->fontMetrics().ascent() + urlFont->fontMetrics().descent());
    173         imageSize.setHeight(imageSize.height() + urlStringSize.height());
    174         if (urlStringSize.width() > MaxDragLabelStringWidth) {
    175             imageSize.setWidth(MaxDragLabelWidth);
    176             clipURLString = true;
    177         } else
    178             imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DragLabelBorderX * 2);
    179     }
    180 
    181     // We now know how big the image needs to be, so we create and
    182     // fill the background
    183     HBITMAP image = 0;
    184     HDC dc = GetDC(0);
    185     HDC workingDC = CreateCompatibleDC(dc);
    186     if (!workingDC) {
    187         ReleaseDC(0, dc);
    188         return 0;
    189     }
    190 
    191     PlatformGraphicsContext* contextRef;
    192     image = allocImage(workingDC, imageSize, &contextRef);
    193     if (!image) {
    194         DeleteDC(workingDC);
    195         ReleaseDC(0, dc);
    196         return 0;
    197     }
    198 
    199     SelectObject(workingDC, image);
    200     GraphicsContext context(contextRef);
    201     // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha
    202     // for drag images on win, so we use 1
    203     static const Color backgroundColor(140, 140, 140);
    204     static const IntSize radii(DragLabelRadius, DragLabelRadius);
    205     IntRect rect(0, 0, imageSize.width(), imageSize.height());
    206     context.fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor, ColorSpaceDeviceRGB);
    207 
    208     // Draw the text
    209     static const Color topColor(0, 0, 0, 255); // original alpha = 0.75
    210     static const Color bottomColor(255, 255, 255, 127); // original alpha = 0.5
    211     if (drawURLString) {
    212         if (clipURLString)
    213             urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DragLabelBorderX * 2.0f), *urlFont);
    214         IntPoint textPos(DragLabelBorderX, imageSize.height() - (LabelBorderYOffset + urlFont->fontMetrics().descent()));
    215         WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, topColor, bottomColor);
    216     }
    217 
    218     if (clipLabelString)
    219         label = StringTruncator::rightTruncate(label, imageSize.width() - (DragLabelBorderX * 2.0f), *labelFont);
    220 
    221     IntPoint textPos(DragLabelBorderX, DragLabelBorderY + labelFont->pixelSize());
    222     WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor, bottomColor);
    223 
    224     deallocContext(contextRef);
    225     DeleteDC(workingDC);
    226     ReleaseDC(0, dc);
    227     return image;
    228 }
    229 
    230 }
    231