PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/webview/native/Source/WebCore/platform/graphics/win/FontCacheWin.cpp

https://bitbucket.org/rbair/rbair-controls-8
C++ | 598 lines | 456 code | 85 blank | 57 comment | 106 complexity | 2badbe4e7d96efd864b1d8d8324dd978 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (C) 2006, 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. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include <winsock2.h>
  30. #include "FontCache.h"
  31. #include "Font.h"
  32. #include "HWndDC.h"
  33. #include "SimpleFontData.h"
  34. #include "UnicodeRange.h"
  35. #include <mlang.h>
  36. #include <windows.h>
  37. #include <wtf/StdLibExtras.h>
  38. #include <wtf/text/StringHash.h>
  39. #if USE(CG)
  40. #include <ApplicationServices/ApplicationServices.h>
  41. #include <WebKitSystemInterface/WebKitSystemInterface.h>
  42. #endif
  43. using std::min;
  44. namespace WebCore
  45. {
  46. void FontCache::platformInit()
  47. {
  48. #if USE(CG)
  49. wkSetUpFontCache(1536 * 1024 * 4); // This size matches Mac.
  50. #endif
  51. }
  52. IMLangFontLink2* FontCache::getFontLinkInterface()
  53. {
  54. static IMultiLanguage *multiLanguage;
  55. if (!multiLanguage) {
  56. if (CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_ALL, IID_IMultiLanguage, (void**)&multiLanguage) != S_OK)
  57. return 0;
  58. }
  59. static IMLangFontLink2* langFontLink;
  60. if (!langFontLink) {
  61. if (multiLanguage->QueryInterface(&langFontLink) != S_OK)
  62. return 0;
  63. }
  64. return langFontLink;
  65. }
  66. static int CALLBACK metaFileEnumProc(HDC hdc, HANDLETABLE* table, CONST ENHMETARECORD* record, int tableEntries, LPARAM logFont)
  67. {
  68. if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
  69. const EMREXTCREATEFONTINDIRECTW* createFontRecord = reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
  70. *reinterpret_cast<LOGFONT*>(logFont) = createFontRecord->elfw.elfLogFont;
  71. }
  72. return true;
  73. }
  74. static int CALLBACK linkedFontEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM hfont)
  75. {
  76. *reinterpret_cast<HFONT*>(hfont) = CreateFontIndirect(logFont);
  77. return false;
  78. }
  79. static const Vector<String>* getLinkedFonts(String& family)
  80. {
  81. static HashMap<String, Vector<String>*> systemLinkMap;
  82. Vector<String>* result = systemLinkMap.get(family);
  83. if (result)
  84. return result;
  85. result = new Vector<String>;
  86. systemLinkMap.set(family, result);
  87. HKEY fontLinkKey;
  88. if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink", 0, KEY_READ, &fontLinkKey)))
  89. return result;
  90. DWORD linkedFontsBufferSize = 0;
  91. RegQueryValueEx(fontLinkKey, family.charactersWithNullTermination(), 0, NULL, NULL, &linkedFontsBufferSize);
  92. WCHAR* linkedFonts = reinterpret_cast<WCHAR*>(malloc(linkedFontsBufferSize));
  93. if (SUCCEEDED(RegQueryValueEx(fontLinkKey, family.charactersWithNullTermination(), 0, NULL, reinterpret_cast<BYTE*>(linkedFonts), &linkedFontsBufferSize))) {
  94. unsigned i = 0;
  95. unsigned length = linkedFontsBufferSize / sizeof(*linkedFonts);
  96. while (i < length) {
  97. while (i < length && linkedFonts[i] != ',')
  98. i++;
  99. i++;
  100. unsigned j = i;
  101. while (j < length && linkedFonts[j])
  102. j++;
  103. result->append(String(linkedFonts + i, j - i));
  104. i = j + 1;
  105. }
  106. }
  107. free(linkedFonts);
  108. RegCloseKey(fontLinkKey);
  109. return result;
  110. }
  111. static const Vector<DWORD, 4>& getCJKCodePageMasks()
  112. {
  113. // The default order in which we look for a font for a CJK character. If the user's default code page is
  114. // one of these, we will use it first.
  115. static const UINT CJKCodePages[] = {
  116. 932, /* Japanese */
  117. 936, /* Simplified Chinese */
  118. 950, /* Traditional Chinese */
  119. 949 /* Korean */
  120. };
  121. static Vector<DWORD, 4> codePageMasks;
  122. static bool initialized;
  123. if (!initialized) {
  124. initialized = true;
  125. IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
  126. if (!langFontLink)
  127. return codePageMasks;
  128. UINT defaultCodePage;
  129. DWORD defaultCodePageMask = 0;
  130. if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE, reinterpret_cast<LPWSTR>(&defaultCodePage), sizeof(defaultCodePage)))
  131. langFontLink->CodePageToCodePages(defaultCodePage, &defaultCodePageMask);
  132. if (defaultCodePage == CJKCodePages[0] || defaultCodePage == CJKCodePages[1] || defaultCodePage == CJKCodePages[2] || defaultCodePage == CJKCodePages[3])
  133. codePageMasks.append(defaultCodePageMask);
  134. for (unsigned i = 0; i < 4; ++i) {
  135. if (defaultCodePage != CJKCodePages[i]) {
  136. DWORD codePageMask;
  137. langFontLink->CodePageToCodePages(CJKCodePages[i], &codePageMask);
  138. codePageMasks.append(codePageMask);
  139. }
  140. }
  141. }
  142. return codePageMasks;
  143. }
  144. static bool currentFontContainsCharacter(HDC hdc, UChar character)
  145. {
  146. static Vector<char, 512> glyphsetBuffer;
  147. glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0));
  148. GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data());
  149. GetFontUnicodeRanges(hdc, glyphset);
  150. // FIXME: Change this to a binary search.
  151. unsigned i = 0;
  152. while (i < glyphset->cRanges && glyphset->ranges[i].wcLow <= character)
  153. i++;
  154. return i && glyphset->ranges[i - 1].wcLow + glyphset->ranges[i - 1].cGlyphs > character;
  155. }
  156. static HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codePageMask, UChar character = 0)
  157. {
  158. HFONT MLangFont;
  159. HFONT hfont = 0;
  160. if (SUCCEEDED(langFontLink->MapFont(hdc, codePageMask, character, &MLangFont)) && MLangFont) {
  161. LOGFONT lf;
  162. GetObject(MLangFont, sizeof(LOGFONT), &lf);
  163. langFontLink->ReleaseFont(MLangFont);
  164. hfont = CreateFontIndirect(&lf);
  165. }
  166. return hfont;
  167. }
  168. const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
  169. {
  170. UChar character = characters[0];
  171. SimpleFontData* fontData = 0;
  172. HWndDC hdc(0);
  173. HFONT primaryFont = font.primaryFont()->fontDataForCharacter(character)->platformData().hfont();
  174. HGDIOBJ oldFont = SelectObject(hdc, primaryFont);
  175. HFONT hfont = 0;
  176. if (IMLangFontLink2* langFontLink = getFontLinkInterface()) {
  177. // Try MLang font linking first.
  178. DWORD codePages = 0;
  179. langFontLink->GetCharCodePages(character, &codePages);
  180. if (codePages && findCharUnicodeRange(character) == cRangeSetCJK) {
  181. // The CJK character may belong to multiple code pages. We want to
  182. // do font linking against a single one of them, preferring the default
  183. // code page for the user's locale.
  184. const Vector<DWORD, 4>& CJKCodePageMasks = getCJKCodePageMasks();
  185. unsigned numCodePages = CJKCodePageMasks.size();
  186. for (unsigned i = 0; i < numCodePages && !hfont; ++i) {
  187. hfont = createMLangFont(langFontLink, hdc, CJKCodePageMasks[i]);
  188. if (hfont && !(codePages & CJKCodePageMasks[i])) {
  189. // We asked about a code page that is not one of the code pages
  190. // returned by MLang, so the font might not contain the character.
  191. SelectObject(hdc, hfont);
  192. if (!currentFontContainsCharacter(hdc, character)) {
  193. DeleteObject(hfont);
  194. hfont = 0;
  195. }
  196. SelectObject(hdc, primaryFont);
  197. }
  198. }
  199. } else
  200. hfont = createMLangFont(langFontLink, hdc, codePages, character);
  201. }
  202. // A font returned from MLang is trusted to contain the character.
  203. bool containsCharacter = hfont;
  204. if (!hfont) {
  205. // To find out what font Uniscribe would use, we make it draw into a metafile and intercept
  206. // calls to CreateFontIndirect().
  207. HDC metaFileDc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
  208. SelectObject(metaFileDc, primaryFont);
  209. bool scriptStringOutSucceeded = false;
  210. SCRIPT_STRING_ANALYSIS ssa;
  211. // FIXME: If length is greater than 1, we actually return the font for the last character.
  212. // This function should be renamed getFontDataForCharacter and take a single 32-bit character.
  213. if (SUCCEEDED(ScriptStringAnalyse(metaFileDc, characters, length, 0, -1, SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
  214. 0, NULL, NULL, NULL, NULL, NULL, &ssa))) {
  215. scriptStringOutSucceeded = SUCCEEDED(ScriptStringOut(ssa, 0, 0, 0, NULL, 0, 0, FALSE));
  216. ScriptStringFree(&ssa);
  217. }
  218. HENHMETAFILE metaFile = CloseEnhMetaFile(metaFileDc);
  219. if (scriptStringOutSucceeded) {
  220. LOGFONT logFont;
  221. logFont.lfFaceName[0] = 0;
  222. EnumEnhMetaFile(0, metaFile, metaFileEnumProc, &logFont, NULL);
  223. if (logFont.lfFaceName[0])
  224. hfont = CreateFontIndirect(&logFont);
  225. }
  226. DeleteEnhMetaFile(metaFile);
  227. }
  228. String familyName;
  229. const Vector<String>* linkedFonts = 0;
  230. unsigned linkedFontIndex = 0;
  231. while (hfont) {
  232. SelectObject(hdc, hfont);
  233. WCHAR name[LF_FACESIZE];
  234. GetTextFace(hdc, LF_FACESIZE, name);
  235. familyName = name;
  236. if (containsCharacter || currentFontContainsCharacter(hdc, character))
  237. break;
  238. if (!linkedFonts)
  239. linkedFonts = getLinkedFonts(familyName);
  240. SelectObject(hdc, oldFont);
  241. DeleteObject(hfont);
  242. hfont = 0;
  243. if (linkedFonts->size() <= linkedFontIndex)
  244. break;
  245. LOGFONT logFont;
  246. logFont.lfCharSet = DEFAULT_CHARSET;
  247. memcpy(logFont.lfFaceName, linkedFonts->at(linkedFontIndex).characters(), linkedFonts->at(linkedFontIndex).length() * sizeof(WCHAR));
  248. logFont.lfFaceName[linkedFonts->at(linkedFontIndex).length()] = 0;
  249. EnumFontFamiliesEx(hdc, &logFont, linkedFontEnumProc, reinterpret_cast<LPARAM>(&hfont), 0);
  250. linkedFontIndex++;
  251. }
  252. if (hfont) {
  253. if (!familyName.isEmpty()) {
  254. FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName);
  255. if (result)
  256. fontData = getCachedFontData(result, DoNotRetain);
  257. }
  258. SelectObject(hdc, oldFont);
  259. DeleteObject(hfont);
  260. }
  261. return fontData;
  262. }
  263. SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
  264. {
  265. return 0;
  266. }
  267. SimpleFontData* FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName)
  268. {
  269. AtomicString familyName = String(font.lfFaceName, wcsnlen(font.lfFaceName, LF_FACESIZE));
  270. SimpleFontData* fontData = getCachedFontData(fontDescription, familyName, false, shouldRetain);
  271. if (fontData)
  272. outFontFamilyName = familyName;
  273. return fontData;
  274. }
  275. SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain)
  276. {
  277. DEFINE_STATIC_LOCAL(AtomicString, fallbackFontName, ());
  278. if (!fallbackFontName.isEmpty())
  279. return getCachedFontData(fontDescription, fallbackFontName, false, shouldRetain);
  280. // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick
  281. // the default that the user would get without changing any prefs.
  282. // Search all typical Windows-installed full Unicode fonts.
  283. // Sorted by most to least glyphs according to http://en.wikipedia.org/wiki/Unicode_typefaces
  284. // Start with Times New Roman also since it is the default if the user doesn't change prefs.
  285. static AtomicString fallbackFonts[] = {
  286. AtomicString("Times New Roman"),
  287. AtomicString("Microsoft Sans Serif"),
  288. AtomicString("Tahoma"),
  289. AtomicString("Lucida Sans Unicode"),
  290. AtomicString("Arial")
  291. };
  292. SimpleFontData* simpleFont;
  293. for (size_t i = 0; i < WTF_ARRAY_LENGTH(fallbackFonts); ++i) {
  294. if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i]), false, shouldRetain) {
  295. fallbackFontName = fallbackFonts[i];
  296. return simpleFont;
  297. }
  298. }
  299. // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
  300. if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
  301. LOGFONT defaultGUILogFont;
  302. GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
  303. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, defaultGUILogFont, fallbackFontName))
  304. return simpleFont;
  305. }
  306. // Fall back to Non-client metrics fonts.
  307. NONCLIENTMETRICS nonClientMetrics = {0};
  308. nonClientMetrics.cbSize = sizeof(nonClientMetrics);
  309. if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
  310. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName))
  311. return simpleFont;
  312. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName))
  313. return simpleFont;
  314. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName))
  315. return simpleFont;
  316. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName))
  317. return simpleFont;
  318. if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
  319. return simpleFont;
  320. }
  321. ASSERT_NOT_REACHED();
  322. return 0;
  323. }
  324. static LONG toGDIFontWeight(FontWeight fontWeight)
  325. {
  326. static LONG gdiFontWeights[] = {
  327. FW_THIN, // FontWeight100
  328. FW_EXTRALIGHT, // FontWeight200
  329. FW_LIGHT, // FontWeight300
  330. FW_NORMAL, // FontWeight400
  331. FW_MEDIUM, // FontWeight500
  332. FW_SEMIBOLD, // FontWeight600
  333. FW_BOLD, // FontWeight700
  334. FW_EXTRABOLD, // FontWeight800
  335. FW_HEAVY // FontWeight900
  336. };
  337. return gdiFontWeights[fontWeight];
  338. }
  339. static inline bool isGDIFontWeightBold(LONG gdiFontWeight)
  340. {
  341. return gdiFontWeight >= FW_SEMIBOLD;
  342. }
  343. static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family)
  344. {
  345. static AtomicString lucidaStr("Lucida Grande");
  346. if (equalIgnoringCase(family, lucidaStr)) {
  347. if (gdiFontWeight == FW_NORMAL)
  348. return FW_MEDIUM;
  349. if (gdiFontWeight == FW_BOLD)
  350. return FW_SEMIBOLD;
  351. }
  352. return gdiFontWeight;
  353. }
  354. struct MatchImprovingProcData {
  355. MatchImprovingProcData(LONG desiredWeight, bool desiredItalic)
  356. : m_desiredWeight(desiredWeight)
  357. , m_desiredItalic(desiredItalic)
  358. , m_hasMatched(false)
  359. {
  360. }
  361. LONG m_desiredWeight;
  362. bool m_desiredItalic;
  363. bool m_hasMatched;
  364. LOGFONT m_chosen;
  365. };
  366. static int CALLBACK matchImprovingEnumProc(CONST LOGFONT* candidate, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
  367. {
  368. MatchImprovingProcData* matchData = reinterpret_cast<MatchImprovingProcData*>(lParam);
  369. if (!matchData->m_hasMatched) {
  370. matchData->m_hasMatched = true;
  371. matchData->m_chosen = *candidate;
  372. return 1;
  373. }
  374. if (!candidate->lfItalic != !matchData->m_chosen.lfItalic) {
  375. if (!candidate->lfItalic == !matchData->m_desiredItalic)
  376. matchData->m_chosen = *candidate;
  377. return 1;
  378. }
  379. unsigned chosenWeightDeltaMagnitude = abs(matchData->m_chosen.lfWeight - matchData->m_desiredWeight);
  380. unsigned candidateWeightDeltaMagnitude = abs(candidate->lfWeight - matchData->m_desiredWeight);
  381. // If both are the same distance from the desired weight, prefer the candidate if it is further from regular.
  382. if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude && abs(candidate->lfWeight - FW_NORMAL) > abs(matchData->m_chosen.lfWeight - FW_NORMAL)) {
  383. matchData->m_chosen = *candidate;
  384. return 1;
  385. }
  386. // Otherwise, prefer the one closer to the desired weight.
  387. if (candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude)
  388. matchData->m_chosen = *candidate;
  389. return 1;
  390. }
  391. static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool desiredItalic, int size, bool synthesizeItalic)
  392. {
  393. HWndDC hdc(0);
  394. LOGFONT logFont;
  395. logFont.lfCharSet = DEFAULT_CHARSET;
  396. unsigned familyLength = min(family.length(), static_cast<unsigned>(LF_FACESIZE - 1));
  397. memcpy(logFont.lfFaceName, family.characters(), familyLength * sizeof(UChar));
  398. logFont.lfFaceName[familyLength] = 0;
  399. logFont.lfPitchAndFamily = 0;
  400. MatchImprovingProcData matchData(desiredWeight, desiredItalic);
  401. EnumFontFamiliesEx(hdc, &logFont, matchImprovingEnumProc, reinterpret_cast<LPARAM>(&matchData), 0);
  402. if (!matchData.m_hasMatched)
  403. return 0;
  404. matchData.m_chosen.lfHeight = -size;
  405. matchData.m_chosen.lfWidth = 0;
  406. matchData.m_chosen.lfEscapement = 0;
  407. matchData.m_chosen.lfOrientation = 0;
  408. matchData.m_chosen.lfUnderline = false;
  409. matchData.m_chosen.lfStrikeOut = false;
  410. matchData.m_chosen.lfCharSet = DEFAULT_CHARSET;
  411. #if USE(CG) || USE(CAIRO)
  412. matchData.m_chosen.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  413. #else
  414. matchData.m_chosen.lfOutPrecision = OUT_TT_PRECIS;
  415. #endif
  416. matchData.m_chosen.lfQuality = DEFAULT_QUALITY;
  417. matchData.m_chosen.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  418. if (desiredItalic && !matchData.m_chosen.lfItalic && synthesizeItalic)
  419. matchData.m_chosen.lfItalic = 1;
  420. HFONT result = CreateFontIndirect(&matchData.m_chosen);
  421. if (!result)
  422. return 0;
  423. HWndDC dc(0);
  424. SaveDC(dc);
  425. SelectObject(dc, result);
  426. WCHAR actualName[LF_FACESIZE];
  427. GetTextFace(dc, LF_FACESIZE, actualName);
  428. RestoreDC(dc, -1);
  429. if (wcsicmp(matchData.m_chosen.lfFaceName, actualName)) {
  430. DeleteObject(result);
  431. result = 0;
  432. }
  433. return result;
  434. }
  435. struct TraitsInFamilyProcData {
  436. TraitsInFamilyProcData(const AtomicString& familyName)
  437. : m_familyName(familyName)
  438. {
  439. }
  440. const AtomicString& m_familyName;
  441. HashSet<unsigned> m_traitsMasks;
  442. };
  443. static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
  444. {
  445. TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
  446. unsigned traitsMask = 0;
  447. traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
  448. traitsMask |= FontVariantNormalMask;
  449. LONG weight = adjustedGDIFontWeight(logFont->lfWeight, procData->m_familyName);
  450. traitsMask |= weight == FW_THIN ? FontWeight100Mask :
  451. weight == FW_EXTRALIGHT ? FontWeight200Mask :
  452. weight == FW_LIGHT ? FontWeight300Mask :
  453. weight == FW_NORMAL ? FontWeight400Mask :
  454. weight == FW_MEDIUM ? FontWeight500Mask :
  455. weight == FW_SEMIBOLD ? FontWeight600Mask :
  456. weight == FW_BOLD ? FontWeight700Mask :
  457. weight == FW_EXTRABOLD ? FontWeight800Mask :
  458. FontWeight900Mask;
  459. procData->m_traitsMasks.add(traitsMask);
  460. return 1;
  461. }
  462. void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
  463. {
  464. HWndDC hdc(0);
  465. LOGFONT logFont;
  466. logFont.lfCharSet = DEFAULT_CHARSET;
  467. unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
  468. memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
  469. logFont.lfFaceName[familyLength] = 0;
  470. logFont.lfPitchAndFamily = 0;
  471. TraitsInFamilyProcData procData(familyName);
  472. EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
  473. copyToVector(procData.m_traitsMasks, traitsMasks);
  474. }
  475. FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
  476. {
  477. bool isLucidaGrande = false;
  478. static AtomicString lucidaStr("Lucida Grande");
  479. if (equalIgnoringCase(family, lucidaStr))
  480. isLucidaGrande = true;
  481. bool useGDI = fontDescription.renderingMode() == AlternateRenderingMode && !isLucidaGrande;
  482. // The logical size constant is 32. We do this for subpixel precision when rendering using Uniscribe.
  483. // This masks rounding errors related to the HFONT metrics being different from the CGFont metrics.
  484. // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't
  485. // look as nice. That may be solvable though.
  486. LONG weight = adjustedGDIFontWeight(toGDIFontWeight(fontDescription.weight()), family);
  487. HFONT hfont = createGDIFont(family, weight, fontDescription.italic(),
  488. fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI);
  489. if (!hfont)
  490. return 0;
  491. if (isLucidaGrande)
  492. useGDI = false; // Never use GDI for Lucida Grande.
  493. LOGFONT logFont;
  494. GetObject(hfont, sizeof(LOGFONT), &logFont);
  495. bool synthesizeBold = isGDIFontWeightBold(weight) && !isGDIFontWeightBold(logFont.lfWeight);
  496. bool synthesizeItalic = fontDescription.italic() && !logFont.lfItalic;
  497. FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(), synthesizeBold, synthesizeItalic, useGDI);
  498. #if USE(CG)
  499. bool fontCreationFailed = !result->cgFont();
  500. #elif USE(CAIRO)
  501. bool fontCreationFailed = !result->scaledFont();
  502. #endif
  503. if (fontCreationFailed) {
  504. // The creation of the CGFontRef failed for some reason. We already asserted in debug builds, but to make
  505. // absolutely sure that we don't use this font, go ahead and return 0 so that we can fall back to the next
  506. // font.
  507. delete result;
  508. DeleteObject(hfont);
  509. return 0;
  510. }
  511. return result;
  512. }
  513. }