OLD | NEW |
| (Empty) |
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 "FontCache.h" | |
32 #include "FontDescription.h" | |
33 #include "FontSelector.h" | |
34 #include "Frame.h" | |
35 #include "GraphicsContext.h" | |
36 #include "HWndDC.h" | |
37 #include "Image.h" | |
38 #include "Settings.h" | |
39 #include "StringTruncator.h" | |
40 #include "TextRun.h" | |
41 #include "WebCoreTextRenderer.h" | |
42 #include <wtf/RetainPtr.h> | |
43 | |
44 #include <windows.h> | |
45 | |
46 namespace WebCore { | |
47 | |
48 HBITMAP allocImage(HDC, IntSize, PlatformGraphicsContext** targetRef); | |
49 void deallocContext(PlatformGraphicsContext* target); | |
50 | |
51 IntSize dragImageSize(DragImageRef image) | |
52 { | |
53 if (!image) | |
54 return IntSize(); | |
55 BITMAP b; | |
56 GetObject(image, sizeof(BITMAP), &b); | |
57 return IntSize(b.bmWidth, b.bmHeight); | |
58 } | |
59 | |
60 void deleteDragImage(DragImageRef image) | |
61 { | |
62 if (image) | |
63 ::DeleteObject(image); | |
64 } | |
65 | |
66 DragImageRef dissolveDragImageToFraction(DragImageRef image, float) | |
67 { | |
68 //We don't do this on windows as the dragimage is blended by the OS | |
69 return image; | |
70 } | |
71 | |
72 DragImageRef createDragImageIconForCachedImage(CachedImage* image) | |
73 { | |
74 if (!image) | |
75 return 0; | |
76 | |
77 String filename = image->response().suggestedFilename(); | |
78 | |
79 SHFILEINFO shfi = {0}; | |
80 if (FAILED(SHGetFileInfo(static_cast<LPCWSTR>(filename.charactersWithNullTer
mination()), FILE_ATTRIBUTE_NORMAL, | |
81 &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES))) | |
82 return 0; | |
83 | |
84 ICONINFO iconInfo; | |
85 if (!GetIconInfo(shfi.hIcon, &iconInfo)) { | |
86 DestroyIcon(shfi.hIcon); | |
87 return 0; | |
88 } | |
89 | |
90 DestroyIcon(shfi.hIcon); | |
91 DeleteObject(iconInfo.hbmMask); | |
92 | |
93 return iconInfo.hbmColor; | |
94 } | |
95 | |
96 const float DragLabelBorderX = 4; | |
97 // Keep border_y in synch with DragController::LinkDragBorderInset. | |
98 const float DragLabelBorderY = 2; | |
99 const float DragLabelRadius = 5; | |
100 const float LabelBorderYOffset = 2; | |
101 | |
102 const float MinDragLabelWidthBeforeClip = 120; | |
103 const float MaxDragLabelWidth = 200; | |
104 const float MaxDragLabelStringWidth = (MaxDragLabelWidth - 2 * DragLabelBorderX)
; | |
105 | |
106 const float DragLinkLabelFontsize = 11; | |
107 const float DragLinkUrlFontSize = 10; | |
108 | |
109 static Font dragLabelFont(int size, bool bold, FontRenderingMode renderingMode) | |
110 { | |
111 Font result; | |
112 #if !OS(WINCE) | |
113 NONCLIENTMETRICS metrics; | |
114 metrics.cbSize = sizeof(metrics); | |
115 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); | |
116 | |
117 FontDescription description; | |
118 description.setWeight(bold ? FontWeightBold : FontWeightNormal); | |
119 | |
120 FontFamily family; | |
121 family.setFamily(metrics.lfSmCaptionFont.lfFaceName); | |
122 description.setFamily(family); | |
123 description.setSpecifiedSize((float)size); | |
124 description.setComputedSize((float)size); | |
125 description.setRenderingMode(renderingMode); | |
126 result = Font(description, 0, 0); | |
127 result.update(0); | |
128 #endif | |
129 return result; | |
130 } | |
131 | |
132 DragImageRef createDragImageForLink(KURL& url, const String& inLabel, Frame* fra
me) | |
133 { | |
134 // This is more or less an exact match for the Mac OS X code. | |
135 | |
136 const Font* labelFont; | |
137 const Font* urlFont; | |
138 FontCachePurgePreventer fontCachePurgePreventer; | |
139 | |
140 if (frame->settings() && frame->settings()->fontRenderingMode() == Alternate
RenderingMode) { | |
141 static const Font alternateRenderingModeLabelFont = dragLabelFont(DragLi
nkLabelFontsize, true, AlternateRenderingMode); | |
142 static const Font alternateRenderingModeURLFont = dragLabelFont(DragLink
UrlFontSize, false, AlternateRenderingMode); | |
143 labelFont = &alternateRenderingModeLabelFont; | |
144 urlFont = &alternateRenderingModeURLFont; | |
145 } else { | |
146 static const Font normalRenderingModeLabelFont = dragLabelFont(DragLinkL
abelFontsize, true, NormalRenderingMode); | |
147 static const Font normalRenderingModeURLFont = dragLabelFont(DragLinkUrl
FontSize, false, NormalRenderingMode); | |
148 labelFont = &normalRenderingModeLabelFont; | |
149 urlFont = &normalRenderingModeURLFont; | |
150 } | |
151 | |
152 bool drawURLString = true; | |
153 bool clipURLString = false; | |
154 bool clipLabelString = false; | |
155 | |
156 String urlString = url.string(); | |
157 String label = inLabel; | |
158 if (label.isEmpty()) { | |
159 drawURLString = false; | |
160 label = urlString; | |
161 } | |
162 | |
163 // First step in drawing the link drag image width. | |
164 TextRun labelRun(label.impl()); | |
165 TextRun urlRun(urlString.impl()); | |
166 IntSize labelSize(labelFont->width(labelRun), labelFont->fontMetrics().ascen
t() + labelFont->fontMetrics().descent()); | |
167 | |
168 if (labelSize.width() > MaxDragLabelStringWidth) { | |
169 labelSize.setWidth(MaxDragLabelStringWidth); | |
170 clipLabelString = true; | |
171 } | |
172 | |
173 IntSize urlStringSize; | |
174 IntSize imageSize(labelSize.width() + DragLabelBorderX * 2, labelSize.height
() + DragLabelBorderY * 2); | |
175 | |
176 if (drawURLString) { | |
177 urlStringSize.setWidth(urlFont->width(urlRun)); | |
178 urlStringSize.setHeight(urlFont->fontMetrics().ascent() + urlFont->fontM
etrics().descent()); | |
179 imageSize.setHeight(imageSize.height() + urlStringSize.height()); | |
180 if (urlStringSize.width() > MaxDragLabelStringWidth) { | |
181 imageSize.setWidth(MaxDragLabelWidth); | |
182 clipURLString = true; | |
183 } else | |
184 imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()
) + DragLabelBorderX * 2); | |
185 } | |
186 | |
187 // We now know how big the image needs to be, so we create and | |
188 // fill the background | |
189 HBITMAP image = 0; | |
190 HWndDC dc(0); | |
191 HDC workingDC = CreateCompatibleDC(dc); | |
192 if (!workingDC) | |
193 return 0; | |
194 | |
195 PlatformGraphicsContext* contextRef; | |
196 image = allocImage(workingDC, imageSize, &contextRef); | |
197 if (!image) { | |
198 DeleteDC(workingDC); | |
199 return 0; | |
200 } | |
201 | |
202 SelectObject(workingDC, image); | |
203 GraphicsContext context(contextRef); | |
204 // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha | |
205 // for drag images on win, so we use 1 | |
206 static const Color backgroundColor(140, 140, 140); | |
207 static const IntSize radii(DragLabelRadius, DragLabelRadius); | |
208 IntRect rect(0, 0, imageSize.width(), imageSize.height()); | |
209 context.fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor, C
olorSpaceDeviceRGB); | |
210 | |
211 // Draw the text | |
212 static const Color topColor(0, 0, 0, 255); // original alpha = 0.75 | |
213 static const Color bottomColor(255, 255, 255, 127); // original alpha = 0.5 | |
214 if (drawURLString) { | |
215 if (clipURLString) | |
216 urlString = StringTruncator::rightTruncate(urlString, imageSize.widt
h() - (DragLabelBorderX * 2.0f), *urlFont, StringTruncator::EnableRoundingHacks)
; | |
217 IntPoint textPos(DragLabelBorderX, imageSize.height() - (LabelBorderYOff
set + urlFont->fontMetrics().descent())); | |
218 WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, top
Color, bottomColor); | |
219 } | |
220 | |
221 if (clipLabelString) | |
222 label = StringTruncator::rightTruncate(label, imageSize.width() - (DragL
abelBorderX * 2.0f), *labelFont, StringTruncator::EnableRoundingHacks); | |
223 | |
224 IntPoint textPos(DragLabelBorderX, DragLabelBorderY + labelFont->pixelSize()
); | |
225 WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor,
bottomColor); | |
226 | |
227 deallocContext(contextRef); | |
228 DeleteDC(workingDC); | |
229 return image; | |
230 } | |
231 | |
232 } | |
OLD | NEW |