/platform/external/webkit/WebCore/css/CSSFontSelector.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 538 lines · 419 code · 72 blank · 47 comment · 115 complexity · f76d2c39e9ff94626d213c77b1576c30 MD5 · raw file

  1. /*
  2. * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
  3. * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  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. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "CSSFontSelector.h"
  28. #include "AtomicString.h"
  29. #include "CachedFont.h"
  30. #include "CSSFontFace.h"
  31. #include "CSSFontFaceRule.h"
  32. #include "CSSFontFaceSource.h"
  33. #include "CSSFontFaceSrcValue.h"
  34. #include "CSSMutableStyleDeclaration.h"
  35. #include "CSSPrimitiveValue.h"
  36. #include "CSSPropertyNames.h"
  37. #include "CSSSegmentedFontFace.h"
  38. #include "CSSUnicodeRangeValue.h"
  39. #include "CSSValueKeywords.h"
  40. #include "CSSValueList.h"
  41. #include "DocLoader.h"
  42. #include "Document.h"
  43. #include "FontCache.h"
  44. #include "FontFamilyValue.h"
  45. #include "Frame.h"
  46. #include "RenderObject.h"
  47. #include "Settings.h"
  48. #include "SimpleFontData.h"
  49. #if ENABLE(SVG)
  50. #include "SVGFontFaceElement.h"
  51. #include "SVGNames.h"
  52. #endif
  53. namespace WebCore {
  54. CSSFontSelector::CSSFontSelector(Document* document)
  55. : m_document(document)
  56. {
  57. // FIXME: An old comment used to say there was no need to hold a reference to m_document
  58. // because "we are guaranteed to be destroyed before the document". But there does not
  59. // seem to be any such guarantee.
  60. ASSERT(m_document);
  61. fontCache()->addClient(this);
  62. }
  63. CSSFontSelector::~CSSFontSelector()
  64. {
  65. fontCache()->removeClient(this);
  66. deleteAllValues(m_fontFaces);
  67. deleteAllValues(m_locallyInstalledFontFaces);
  68. deleteAllValues(m_fonts);
  69. }
  70. bool CSSFontSelector::isEmpty() const
  71. {
  72. return m_fonts.isEmpty();
  73. }
  74. DocLoader* CSSFontSelector::docLoader() const
  75. {
  76. return m_document ? m_document->docLoader() : 0;
  77. }
  78. void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule)
  79. {
  80. // Obtain the font-family property and the src property. Both must be defined.
  81. const CSSMutableStyleDeclaration* style = fontFaceRule->style();
  82. RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily);
  83. RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc);
  84. RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange);
  85. if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList()))
  86. return;
  87. CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get());
  88. if (!familyList->length())
  89. return;
  90. CSSValueList* srcList = static_cast<CSSValueList*>(src.get());
  91. if (!srcList->length())
  92. return;
  93. CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get());
  94. unsigned traitsMask = 0;
  95. if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) {
  96. if (fontStyle->isPrimitiveValue()) {
  97. RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
  98. list->append(fontStyle);
  99. fontStyle = list;
  100. } else if (!fontStyle->isValueList())
  101. return;
  102. CSSValueList* styleList = static_cast<CSSValueList*>(fontStyle.get());
  103. unsigned numStyles = styleList->length();
  104. if (!numStyles)
  105. return;
  106. for (unsigned i = 0; i < numStyles; ++i) {
  107. switch (static_cast<CSSPrimitiveValue*>(styleList->itemWithoutBoundsCheck(i))->getIdent()) {
  108. case CSSValueAll:
  109. traitsMask |= FontStyleMask;
  110. break;
  111. case CSSValueNormal:
  112. traitsMask |= FontStyleNormalMask;
  113. break;
  114. case CSSValueItalic:
  115. case CSSValueOblique:
  116. traitsMask |= FontStyleItalicMask;
  117. break;
  118. default:
  119. break;
  120. }
  121. }
  122. } else
  123. traitsMask |= FontStyleMask;
  124. if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight)) {
  125. if (fontWeight->isPrimitiveValue()) {
  126. RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
  127. list->append(fontWeight);
  128. fontWeight = list;
  129. } else if (!fontWeight->isValueList())
  130. return;
  131. CSSValueList* weightList = static_cast<CSSValueList*>(fontWeight.get());
  132. unsigned numWeights = weightList->length();
  133. if (!numWeights)
  134. return;
  135. for (unsigned i = 0; i < numWeights; ++i) {
  136. switch (static_cast<CSSPrimitiveValue*>(weightList->itemWithoutBoundsCheck(i))->getIdent()) {
  137. case CSSValueAll:
  138. traitsMask |= FontWeightMask;
  139. break;
  140. case CSSValueBolder:
  141. case CSSValueBold:
  142. case CSSValue700:
  143. traitsMask |= FontWeight700Mask;
  144. break;
  145. case CSSValueNormal:
  146. case CSSValue400:
  147. traitsMask |= FontWeight400Mask;
  148. break;
  149. case CSSValue900:
  150. traitsMask |= FontWeight900Mask;
  151. break;
  152. case CSSValue800:
  153. traitsMask |= FontWeight800Mask;
  154. break;
  155. case CSSValue600:
  156. traitsMask |= FontWeight600Mask;
  157. break;
  158. case CSSValue500:
  159. traitsMask |= FontWeight500Mask;
  160. break;
  161. case CSSValue300:
  162. traitsMask |= FontWeight300Mask;
  163. break;
  164. case CSSValueLighter:
  165. case CSSValue200:
  166. traitsMask |= FontWeight200Mask;
  167. break;
  168. case CSSValue100:
  169. traitsMask |= FontWeight100Mask;
  170. break;
  171. default:
  172. break;
  173. }
  174. }
  175. } else
  176. traitsMask |= FontWeightMask;
  177. if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSSPropertyFontVariant)) {
  178. if (fontVariant->isPrimitiveValue()) {
  179. RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
  180. list->append(fontVariant);
  181. fontVariant = list;
  182. } else if (!fontVariant->isValueList())
  183. return;
  184. CSSValueList* variantList = static_cast<CSSValueList*>(fontVariant.get());
  185. unsigned numVariants = variantList->length();
  186. if (!numVariants)
  187. return;
  188. for (unsigned i = 0; i < numVariants; ++i) {
  189. switch (static_cast<CSSPrimitiveValue*>(variantList->itemWithoutBoundsCheck(i))->getIdent()) {
  190. case CSSValueAll:
  191. traitsMask |= FontVariantMask;
  192. break;
  193. case CSSValueNormal:
  194. traitsMask |= FontVariantNormalMask;
  195. break;
  196. case CSSValueSmallCaps:
  197. traitsMask |= FontVariantSmallCapsMask;
  198. break;
  199. default:
  200. break;
  201. }
  202. }
  203. } else
  204. traitsMask |= FontVariantNormalMask;
  205. // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
  206. RefPtr<CSSFontFace> fontFace;
  207. int srcLength = srcList->length();
  208. bool foundLocal = false;
  209. bool foundSVGFont = false;
  210. for (int i = 0; i < srcLength; i++) {
  211. // An item in the list either specifies a string (local font name) or a URL (remote font to download).
  212. CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->itemWithoutBoundsCheck(i));
  213. CSSFontFaceSource* source = 0;
  214. #if ENABLE(SVG_FONTS)
  215. foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
  216. #endif
  217. if (!item->isLocal()) {
  218. Settings* settings = m_document ? m_document->frame() ? m_document->frame()->settings() : 0 : 0;
  219. bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled());
  220. if (allowDownloading && item->isSupportedFormat() && m_document) {
  221. CachedFont* cachedFont = m_document->docLoader()->requestFont(item->resource());
  222. if (cachedFont) {
  223. #if ENABLE(SVG_FONTS)
  224. if (foundSVGFont)
  225. cachedFont->setSVGFont(true);
  226. #endif
  227. source = new CSSFontFaceSource(item->resource(), cachedFont);
  228. }
  229. }
  230. } else {
  231. source = new CSSFontFaceSource(item->resource());
  232. foundLocal = true;
  233. }
  234. if (!fontFace)
  235. fontFace = CSSFontFace::create(static_cast<FontTraitsMask>(traitsMask));
  236. if (source) {
  237. #if ENABLE(SVG_FONTS)
  238. source->setSVGFontFaceElement(item->svgFontFaceElement());
  239. #endif
  240. fontFace->addSource(source);
  241. }
  242. }
  243. ASSERT(fontFace);
  244. if (fontFace && !fontFace->isValid())
  245. return;
  246. if (rangeList) {
  247. unsigned numRanges = rangeList->length();
  248. for (unsigned i = 0; i < numRanges; i++) {
  249. CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->itemWithoutBoundsCheck(i));
  250. fontFace->addRange(range->from(), range->to());
  251. }
  252. }
  253. // Hash under every single family name.
  254. int familyLength = familyList->length();
  255. for (int i = 0; i < familyLength; i++) {
  256. CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i));
  257. String familyName;
  258. if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING)
  259. familyName = static_cast<FontFamilyValue*>(item)->familyName();
  260. else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
  261. // We need to use the raw text for all the generic family types, since @font-face is a way of actually
  262. // defining what font to use for those types.
  263. String familyName;
  264. switch (item->getIdent()) {
  265. case CSSValueSerif:
  266. familyName = "-webkit-serif";
  267. break;
  268. case CSSValueSansSerif:
  269. familyName = "-webkit-sans-serif";
  270. break;
  271. case CSSValueCursive:
  272. familyName = "-webkit-cursive";
  273. break;
  274. case CSSValueFantasy:
  275. familyName = "-webkit-fantasy";
  276. break;
  277. case CSSValueMonospace:
  278. familyName = "-webkit-monospace";
  279. break;
  280. default:
  281. break;
  282. }
  283. }
  284. if (familyName.isEmpty())
  285. continue;
  286. #if ENABLE(SVG_FONTS)
  287. // SVG allows several <font> elements with the same font-family, differing only
  288. // in ie. font-variant. Be sure to pick up the right one - in getFontData below.
  289. if (foundSVGFont && (traitsMask & FontVariantSmallCapsMask))
  290. familyName += "-webkit-svg-small-caps";
  291. #endif
  292. Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(familyName);
  293. if (!familyFontFaces) {
  294. familyFontFaces = new Vector<RefPtr<CSSFontFace> >;
  295. m_fontFaces.set(familyName, familyFontFaces);
  296. ASSERT(!m_locallyInstalledFontFaces.contains(familyName));
  297. Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFaces;
  298. Vector<unsigned> locallyInstalledFontsTraitsMasks;
  299. fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks);
  300. unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size();
  301. if (numLocallyInstalledFaces) {
  302. familyLocallyInstalledFaces = new Vector<RefPtr<CSSFontFace> >;
  303. m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces);
  304. for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) {
  305. RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]));
  306. locallyInstalledFontFace->addSource(new CSSFontFaceSource(familyName));
  307. ASSERT(locallyInstalledFontFace->isValid());
  308. familyLocallyInstalledFaces->append(locallyInstalledFontFace);
  309. }
  310. }
  311. }
  312. familyFontFaces->append(fontFace);
  313. }
  314. }
  315. void CSSFontSelector::fontLoaded()
  316. {
  317. if (!m_document || m_document->inPageCache() || !m_document->renderer())
  318. return;
  319. m_document->recalcStyle(Document::Force);
  320. m_document->renderer()->setNeedsLayoutAndPrefWidthsRecalc();
  321. }
  322. void CSSFontSelector::fontCacheInvalidated()
  323. {
  324. if (!m_document || m_document->inPageCache() || !m_document->renderer())
  325. return;
  326. m_document->recalcStyle(Document::Force);
  327. m_document->renderer()->setNeedsLayoutAndPrefWidthsRecalc();
  328. }
  329. static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName)
  330. {
  331. if (!document || !document->frame())
  332. return 0;
  333. const Settings* settings = document->frame()->settings();
  334. if (!settings)
  335. return 0;
  336. AtomicString genericFamily;
  337. if (familyName == "-webkit-serif")
  338. genericFamily = settings->serifFontFamily();
  339. else if (familyName == "-webkit-sans-serif")
  340. genericFamily = settings->sansSerifFontFamily();
  341. else if (familyName == "-webkit-cursive")
  342. genericFamily = settings->cursiveFontFamily();
  343. else if (familyName == "-webkit-fantasy")
  344. genericFamily = settings->fantasyFontFamily();
  345. else if (familyName == "-webkit-monospace")
  346. genericFamily = settings->fixedFontFamily();
  347. else if (familyName == "-webkit-standard")
  348. genericFamily = settings->standardFontFamily();
  349. if (!genericFamily.isEmpty())
  350. return fontCache()->getCachedFontData(fontDescription, genericFamily);
  351. return 0;
  352. }
  353. static FontTraitsMask desiredTraitsMaskForComparison;
  354. static inline bool compareFontFaces(CSSFontFace* first, CSSFontFace* second)
  355. {
  356. FontTraitsMask firstTraitsMask = first->traitsMask();
  357. FontTraitsMask secondTraitsMask = second->traitsMask();
  358. bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
  359. bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
  360. if (firstHasDesiredVariant != secondHasDesiredVariant)
  361. return firstHasDesiredVariant;
  362. bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
  363. bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
  364. if (firstHasDesiredStyle != secondHasDesiredStyle)
  365. return firstHasDesiredStyle;
  366. if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
  367. return false;
  368. if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
  369. return true;
  370. // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#q46 says: "If there are fewer then 9 weights in the family, the default algorithm
  371. // for filling the "holes" is as follows. If '500' is unassigned, it will be assigned the same font as '400'. If any of the values '600',
  372. // '700', '800', or '900' remains unassigned, they are assigned to the same face as the next darker assigned keyword, if any, or the next
  373. // lighter one otherwise. If any of '300', '200', or '100' remains unassigned, it is assigned to the next lighter assigned keyword, if any,
  374. // or the next darker otherwise."
  375. // For '400', we made up our own rule (which then '500' follows).
  376. static const unsigned fallbackRuleSets = 9;
  377. static const unsigned rulesPerSet = 8;
  378. static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {
  379. { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
  380. { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
  381. { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
  382. { FontWeight500Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
  383. { FontWeight400Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
  384. { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
  385. { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
  386. { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
  387. { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }
  388. };
  389. unsigned ruleSetIndex = 0;
  390. unsigned w = FontWeight100Bit;
  391. while (!(desiredTraitsMaskForComparison & (1 << w))) {
  392. w++;
  393. ruleSetIndex++;
  394. }
  395. ASSERT(ruleSetIndex < fallbackRuleSets);
  396. const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
  397. for (unsigned i = 0; i < rulesPerSet; ++i) {
  398. if (secondTraitsMask & weightFallbackRule[i])
  399. return false;
  400. if (firstTraitsMask & weightFallbackRule[i])
  401. return true;
  402. }
  403. return false;
  404. }
  405. FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
  406. {
  407. if (m_fontFaces.isEmpty()) {
  408. if (familyName.startsWith("-webkit-"))
  409. return fontDataForGenericFamily(m_document, fontDescription, familyName);
  410. return 0;
  411. }
  412. String family = familyName.string();
  413. #if ENABLE(SVG_FONTS)
  414. if (fontDescription.smallCaps())
  415. family += "-webkit-svg-small-caps";
  416. #endif
  417. Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
  418. // If no face was found, then return 0 and let the OS come up with its best match for the name.
  419. if (!familyFontFaces || familyFontFaces->isEmpty()) {
  420. // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our
  421. // settings.
  422. return fontDataForGenericFamily(m_document, fontDescription, familyName);
  423. }
  424. HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >* segmentedFontFaceCache = m_fonts.get(family);
  425. if (!segmentedFontFaceCache) {
  426. segmentedFontFaceCache = new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >;
  427. m_fonts.set(family, segmentedFontFaceCache);
  428. }
  429. FontTraitsMask traitsMask = fontDescription.traitsMask();
  430. RefPtr<CSSSegmentedFontFace> face = segmentedFontFaceCache->get(traitsMask);
  431. if (!face) {
  432. face = CSSSegmentedFontFace::create(this);
  433. segmentedFontFaceCache->set(traitsMask, face);
  434. // Collect all matching faces and sort them in order of preference.
  435. Vector<CSSFontFace*, 32> candidateFontFaces;
  436. for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
  437. CSSFontFace* candidate = familyFontFaces->at(i).get();
  438. unsigned candidateTraitsMask = candidate->traitsMask();
  439. if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
  440. continue;
  441. if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
  442. continue;
  443. candidateFontFaces.append(candidate);
  444. }
  445. if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
  446. unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
  447. for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
  448. CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
  449. unsigned candidateTraitsMask = candidate->traitsMask();
  450. if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
  451. continue;
  452. if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
  453. continue;
  454. candidateFontFaces.append(candidate);
  455. }
  456. }
  457. desiredTraitsMaskForComparison = traitsMask;
  458. std::stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
  459. unsigned numCandidates = candidateFontFaces.size();
  460. for (unsigned i = 0; i < numCandidates; ++i)
  461. face->appendFontFace(candidateFontFaces[i]);
  462. }
  463. // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over.
  464. return face->getFontData(fontDescription);
  465. }
  466. }