• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dragImageSize(DragImageRef image)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 
deleteDragImage(DragImageRef image)58 void deleteDragImage(DragImageRef image)
59 {
60     if (image)
61         ::DeleteObject(image);
62 }
63 
dissolveDragImageToFraction(DragImageRef image,float)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 
createDragImageIconForCachedImage(CachedImage * image)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 
dragLabelFont(int size,bool bold,FontRenderingMode renderingMode)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 
createDragImageForLink(KURL & url,const String & inLabel,Frame * frame)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