1 /* 2 * Copyright (C) 2012 Google 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 "core/rendering/RenderThemeChromiumFontProvider.h" 28 29 #include <windows.h> 30 31 #include "CSSValueKeywords.h" 32 #include "core/platform/graphics/FontDescription.h" 33 #include "core/platform/win/HWndDC.h" 34 #include "core/platform/win/SystemInfo.h" 35 #include "wtf/text/WTFString.h" 36 37 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \ 38 offsetof(structName, member) + \ 39 (sizeof static_cast<structName*>(0)->member) 40 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \ 41 SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont) 42 43 namespace WebCore { 44 45 static FontDescription& smallSystemFont() 46 { 47 DEFINE_STATIC_LOCAL(FontDescription, font, ()); 48 return font; 49 } 50 51 static FontDescription& menuFont() 52 { 53 DEFINE_STATIC_LOCAL(FontDescription, font, ()); 54 return font; 55 } 56 57 static FontDescription& labelFont() 58 { 59 DEFINE_STATIC_LOCAL(FontDescription, font, ()); 60 return font; 61 } 62 63 // Converts |points| to pixels. One point is 1/72 of an inch. 64 static float pointsToPixels(float points) 65 { 66 static float pixelsPerInch = 0.0f; 67 if (!pixelsPerInch) { 68 HWndDC hdc(0); // What about printing? Is this the right DC? 69 if (hdc) // Can this ever actually be 0? 70 pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY); 71 else 72 pixelsPerInch = 96.0f; 73 } 74 75 static const float pointsPerInch = 72.0f; 76 return points / pointsPerInch * pixelsPerInch; 77 } 78 79 static void getNonClientMetrics(NONCLIENTMETRICS* metrics) 80 { 81 static UINT size = (windowsVersion() >= WindowsVista) ? 82 sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA; 83 metrics->cbSize = size; 84 bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0); 85 ASSERT(success); 86 } 87 88 // Return the height of system font |font| in pixels. We use this size by 89 // default for some non-form-control elements. 90 static float systemFontSize(const LOGFONT& font) 91 { 92 float size = -font.lfHeight; 93 if (size < 0) { 94 HFONT hFont = CreateFontIndirect(&font); 95 if (hFont) { 96 HWndDC hdc(0); // What about printing? Is this the right DC? 97 if (hdc) { 98 HGDIOBJ hObject = SelectObject(hdc, hFont); 99 TEXTMETRIC tm; 100 GetTextMetrics(hdc, &tm); 101 SelectObject(hdc, hObject); 102 size = tm.tmAscent; 103 } 104 DeleteObject(hFont); 105 } 106 } 107 108 // The "codepage 936" bit here is from Gecko; apparently this helps make 109 // fonts more legible in Simplified Chinese where the default font size is 110 // too small. 111 // 112 // FIXME: http://b/1119883 Since this is only used for "small caption", 113 // "menu", and "status bar" objects, I'm not sure how much this even 114 // matters. Plus the Gecko patch went in back in 2002, and maybe this 115 // isn't even relevant anymore. We should investigate whether this should 116 // be removed, or perhaps broadened to be "any CJK locale". 117 // 118 return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size; 119 } 120 121 // static 122 void RenderThemeChromiumFontProvider::systemFont(CSSValueID valueID, FontDescription& fontDescription) 123 { 124 // This logic owes much to RenderThemeSafari.cpp. 125 FontDescription* cachedDesc = 0; 126 AtomicString faceName; 127 float fontSize = 0; 128 switch (valueID) { 129 case CSSValueSmallCaption: 130 cachedDesc = &smallSystemFont(); 131 if (!smallSystemFont().isAbsoluteSize()) { 132 NONCLIENTMETRICS metrics; 133 getNonClientMetrics(&metrics); 134 faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName)); 135 fontSize = systemFontSize(metrics.lfSmCaptionFont); 136 } 137 break; 138 case CSSValueMenu: 139 cachedDesc = &menuFont(); 140 if (!menuFont().isAbsoluteSize()) { 141 NONCLIENTMETRICS metrics; 142 getNonClientMetrics(&metrics); 143 faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName)); 144 fontSize = systemFontSize(metrics.lfMenuFont); 145 } 146 break; 147 case CSSValueStatusBar: 148 cachedDesc = &labelFont(); 149 if (!labelFont().isAbsoluteSize()) { 150 NONCLIENTMETRICS metrics; 151 getNonClientMetrics(&metrics); 152 faceName = metrics.lfStatusFont.lfFaceName; 153 fontSize = systemFontSize(metrics.lfStatusFont); 154 } 155 break; 156 case CSSValueWebkitMiniControl: 157 case CSSValueWebkitSmallControl: 158 case CSSValueWebkitControl: 159 faceName = defaultGUIFont(); 160 // Why 2 points smaller? Because that's what Gecko does. 161 fontSize = s_defaultFontSize - pointsToPixels(2); 162 break; 163 default: 164 faceName = defaultGUIFont(); 165 fontSize = s_defaultFontSize; 166 break; 167 } 168 169 if (!cachedDesc) 170 cachedDesc = &fontDescription; 171 172 if (fontSize) { 173 cachedDesc->firstFamily().setFamily(faceName); 174 cachedDesc->setIsAbsoluteSize(true); 175 cachedDesc->setGenericFamily(FontDescription::NoFamily); 176 cachedDesc->setSpecifiedSize(fontSize); 177 cachedDesc->setWeight(FontWeightNormal); 178 cachedDesc->setItalic(false); 179 } 180 fontDescription = *cachedDesc; 181 } 182 183 // static 184 void RenderThemeChromiumFontProvider::setDefaultFontSize(int fontSize) 185 { 186 s_defaultFontSize = static_cast<float>(fontSize); 187 188 // Reset cached fonts. 189 smallSystemFont() = menuFont() = labelFont() = FontDescription(); 190 } 191 192 } // namespace WebCore 193