File indexing completed on 2024-04-28 15:22:43
0001 /* 0002 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 0003 * Copyright (C) 2009 Germain Garand <germain@ebooksfrance.org> 0004 * 0005 * Redistribution and use in source and binary forms, with or without 0006 * modification, are permitted provided that the following conditions 0007 * are met: 0008 * 1. Redistributions of source code must retain the above copyright 0009 * notice, this list of conditions and the following disclaimer. 0010 * 2. Redistributions in binary form must reproduce the above copyright 0011 * notice, this list of conditions and the following disclaimer in the 0012 * documentation and/or other materials provided with the distribution. 0013 * 0014 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 0015 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0016 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 0017 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 0018 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 0019 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 0020 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 0021 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 0022 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0024 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 #include "css_webfont.h" 0028 #include "css/css_ruleimpl.h" 0029 #include "css/cssproperties.h" 0030 #include "css/cssvalues.h" 0031 #include "xml/dom_docimpl.h" 0032 #include "rendering/font.h" 0033 #include "rendering/render_object.h" 0034 #include "rendering/render_canvas.h" 0035 #include "khtml_debug.h" 0036 #include <QFontDatabase> 0037 #include <QFont> 0038 0039 namespace DOM 0040 { 0041 0042 CSSFontFaceSource::CSSFontFaceSource(const DOMString &str, bool distant) 0043 : m_string(str) 0044 , m_font(nullptr) 0045 , m_face(nullptr) 0046 , m_refed(false) 0047 , m_distant(distant) 0048 #if 0 0049 //ENABLE(SVG_FONTS) 0050 , m_svgFontFaceElement(0) 0051 #endif 0052 { 0053 m_id = -1; 0054 } 0055 0056 CSSFontFaceSource::~CSSFontFaceSource() 0057 { 0058 if (m_font) { 0059 if (m_refed) { 0060 m_font->deref(this); 0061 } 0062 if (m_id != -1) { 0063 WTF::Vector<DOMString> names = m_face->familyNames(); 0064 unsigned size = names.size(); 0065 for (unsigned i = 0; i < size; i++) { 0066 QFont::removeSubstitutions(names[i].string()); 0067 khtml::Font::invalidateCachedFontFamily(names[i].string()); 0068 } 0069 QFontDatabase::removeApplicationFont(m_id); 0070 } 0071 } 0072 } 0073 0074 bool CSSFontFaceSource::isLoaded() const 0075 { 0076 if (m_distant) { 0077 return m_font ? m_font->isLoaded() : false; 0078 } 0079 return true; 0080 } 0081 0082 bool CSSFontFaceSource::isValid() const 0083 { 0084 if (m_font) { 0085 return !m_font->hadError(); 0086 } 0087 return true; 0088 } 0089 0090 void CSSFontFaceSource::notifyFinished(khtml::CachedObject *finishedObj) 0091 { 0092 // Nothing to do if font already added from other src or failed to download 0093 if (m_face->installed() || finishedObj->hadError()) { 0094 return; 0095 } 0096 0097 WTF::Vector<DOMString> names = m_face->familyNames(); 0098 const unsigned size = names.size(); 0099 0100 m_id = QFontDatabase::addApplicationFontFromData(m_font->font()); 0101 0102 if (m_id == -1) { 0103 // qCDebug(KHTML_LOG) << "WARNING: downloaded web font" << (size?names[0].string():QString()) << "was rejected by the font subsystem."; 0104 return; 0105 } 0106 0107 m_face->setInstalled(); 0108 0109 QString nativeName = QFontDatabase::applicationFontFamilies(m_id)[0]; 0110 for (unsigned i = 0; i < size; i++) { 0111 if (names[i].string() != nativeName) { 0112 QFont::insertSubstitution(names[i].string(), nativeName); 0113 } 0114 khtml::Font::invalidateCachedFontFamily(names[i].string()); 0115 } 0116 0117 if (m_face && m_refed) { 0118 m_face->fontLoaded(this); 0119 } 0120 } 0121 0122 void CSSFontFaceSource::refLoader() 0123 { 0124 if (!m_distant) { 0125 return; 0126 } 0127 if (!m_font) { 0128 assert(m_face); 0129 m_font = m_face->fontSelector()->docLoader()->requestFont(m_string); 0130 } 0131 if (m_font) { 0132 m_font->ref(this); 0133 m_refed = true; 0134 } 0135 } 0136 0137 #if 0 0138 SimpleFontData *CSSFontFaceSource::getFontData(const FontDef &fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector *fontSelector) 0139 { 0140 // If the font hasn't loaded or an error occurred, then we've got nothing. 0141 if (!isValid()) { 0142 return 0; 0143 } 0144 0145 #if 0 0146 // ENABLE(SVG_FONTS) 0147 if (!m_font && !m_svgFontFaceElement) { 0148 #else 0149 if (!m_font) { 0150 #endif 0151 FontPlatformData *data = fontCache()->getCachedFontPlatformData(fontDescription, m_string); 0152 SimpleFontData *fontData = fontCache()->getCachedFontData(data); 0153 0154 // We're local. Just return a SimpleFontData from the normal cache. 0155 return fontData; 0156 } 0157 0158 // See if we have a mapping in our FontData cache. 0159 unsigned hashKey = fontDescription.computedPixelSize() << 2 | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0); 0160 if (SimpleFontData *cachedData = m_fontDataTable.get(hashKey)) { 0161 return cachedData; 0162 } 0163 0164 OwnPtr<SimpleFontData> fontData; 0165 0166 // If we are still loading, then we let the system pick a font. 0167 if (isLoaded()) { 0168 if (m_font) { 0169 #if 0 0170 //ENABLE(SVG_FONTS) 0171 if (m_font->isSVGFont()) { 0172 // For SVG fonts parse the external SVG document, and extract the <font> element. 0173 if (!m_font->ensureSVGFontData()) { 0174 return 0; 0175 } 0176 0177 if (!m_externalSVGFontElement) { 0178 m_externalSVGFontElement = m_font->getSVGFontById(SVGURIReference::getTarget(m_string)); 0179 } 0180 0181 if (!m_externalSVGFontElement) { 0182 return 0; 0183 } 0184 0185 SVGFontFaceElement *fontFaceElement = 0; 0186 0187 // Select first <font-face> child 0188 for (Node *fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) { 0189 if (fontChild->hasTagName(SVGNames::font_faceTag)) { 0190 fontFaceElement = static_cast<SVGFontFaceElement *>(fontChild); 0191 break; 0192 } 0193 } 0194 0195 if (fontFaceElement) { 0196 if (!m_svgFontFaceElement) { 0197 // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement. 0198 // Use the imported <font-face> tag as referencing font-face element for these cases. 0199 m_svgFontFaceElement = fontFaceElement; 0200 } 0201 0202 SVGFontData *svgFontData = new SVGFontData(fontFaceElement); 0203 fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.renderingMode()), true, false, svgFontData)); 0204 } 0205 } else 0206 #endif 0207 { 0208 // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. 0209 if (!m_font->ensureCustomFontData()) { 0210 return 0; 0211 } 0212 0213 fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.renderingMode()), true, false)); 0214 } 0215 } else { 0216 #if 0 0217 //ENABLE(SVG_FONTS) 0218 // In-Document SVG Fonts 0219 if (m_svgFontFaceElement) { 0220 SVGFontData *svgFontData = new SVGFontData(m_svgFontFaceElement); 0221 fontData.set(new SimpleFontData(FontPlatformData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic), true, false, svgFontData)); 0222 } 0223 #endif 0224 } 0225 } else { 0226 // Kick off the load now. 0227 if (DocLoader *docLoader = fontSelector->docLoader()) { 0228 m_font->beginLoadIfNeeded(docLoader); 0229 } 0230 // FIXME: m_string is a URL so it makes no sense to pass it as a family name. 0231 FontPlatformData *tempData = fontCache()->getCachedFontPlatformData(fontDescription, m_string); 0232 if (!tempData) { 0233 tempData = fontCache()->getLastResortFallbackFont(fontDescription); 0234 } 0235 fontData.set(new SimpleFontData(*tempData, true, true)); 0236 } 0237 0238 m_fontDataTable.set(hashKey, fontData.get()); 0239 return fontData.release(); 0240 } 0241 #endif 0242 0243 CSSFontFace::~CSSFontFace() 0244 { 0245 deleteAllValues(m_sources); 0246 } 0247 0248 bool CSSFontFace::isLoaded() const 0249 { 0250 unsigned size = m_sources.size(); 0251 for (unsigned i = 0; i < size; i++) { 0252 if (!m_sources[i]->isLoaded()) { 0253 return false; 0254 } 0255 } 0256 return true; 0257 } 0258 0259 bool CSSFontFace::isValid() const 0260 { 0261 unsigned size = m_sources.size(); 0262 if (!size) { 0263 return false; 0264 } 0265 for (unsigned i = 0; i < size; i++) { 0266 if (m_sources[i]->isValid()) { 0267 return true; 0268 } 0269 } 0270 return false; 0271 } 0272 0273 void CSSFontFace::setInstalled() 0274 { 0275 m_installed = true; 0276 } 0277 0278 bool CSSFontFace::installed() const 0279 { 0280 return m_installed; 0281 } 0282 0283 void CSSFontFace::refLoaders() 0284 { 0285 if (m_refed) { 0286 return; 0287 } 0288 unsigned size = m_sources.size(); 0289 if (!size) { 0290 return; 0291 } 0292 for (unsigned i = 0; i < size; i++) { 0293 m_sources[i]->refLoader(); 0294 } 0295 m_refed = true; 0296 } 0297 0298 void CSSFontFace::addedToSegmentedFontFace(CSSSegmentedFontFace *segmentedFontFace) 0299 { 0300 (void) segmentedFontFace; 0301 // m_segmentedFontFaces.add(segmentedFontFace); 0302 } 0303 0304 void CSSFontFace::removedFromSegmentedFontFace(CSSSegmentedFontFace *segmentedFontFace) 0305 { 0306 (void) segmentedFontFace; 0307 // m_segmentedFontFaces.remove(segmentedFontFace); 0308 } 0309 0310 void CSSFontFace::addSource(CSSFontFaceSource *source) 0311 { 0312 m_sources.append(source); 0313 source->setFontFace(this); 0314 } 0315 0316 void CSSFontFace::fontLoaded(CSSFontFaceSource *) 0317 { 0318 /* 0319 // FIXME: Can we assert that m_segmentedFontFaces is not empty? That may 0320 // require stopping in-progress font loading when the last 0321 // CSSSegmentedFontFace is removed. 0322 if (m_segmentedFontFaces.isEmpty()) 0323 return; 0324 0325 HashSet<CSSSegmentedFontFace*>::iterator end = m_segmentedFontFaces.end(); 0326 for (HashSet<CSSSegmentedFontFace*>::iterator it = m_segmentedFontFaces.begin(); it != end; ++it) 0327 (*it)->fontLoaded(this); 0328 0329 // Use one of the CSSSegmentedFontFaces' font selector. They all have 0330 // the same font selector, so it's wasteful to store it in the CSSFontFace. 0331 CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector(); 0332 */ 0333 m_fontSelector->fontLoaded(); 0334 } 0335 0336 #if 0 0337 SimpleFontData *CSSFontFace::getFontData(const FontDef &fontDescription, bool syntheticBold, bool syntheticItalic) 0338 { 0339 if (!isValid()) { 0340 return 0; 0341 } 0342 0343 ASSERT(!m_segmentedFontFaces.isEmpty()); 0344 CSSFontSelector *fontSelector = (*m_segmentedFontFaces.begin())->fontSelector(); 0345 0346 SimpleFontData *result = 0; 0347 unsigned size = m_sources.size(); 0348 for (unsigned i = 0; i < size && !result; i++) { 0349 result = m_sources[i]->getFontData(fontDescription, syntheticBold, syntheticItalic, fontSelector); 0350 } 0351 return result; 0352 } 0353 #endif 0354 0355 CSSFontSelector::CSSFontSelector(DocumentImpl *document) 0356 : m_document(document) 0357 { 0358 assert(m_document); 0359 // fontCache()->addClient(this); 0360 } 0361 0362 CSSFontSelector::~CSSFontSelector() 0363 { 0364 // fontCache()->removeClient(this); 0365 // deleteAllValues(m_fontFaces); 0366 // deleteAllValues(m_locallyInstalledFontFaces); 0367 // deleteAllValues(m_fonts); 0368 QHash<DOMString, CSSFontFace *>::const_iterator cur = m_locallyInstalledFontFaces.constBegin(); 0369 QHash<DOMString, CSSFontFace *>::const_iterator end = m_locallyInstalledFontFaces.constEnd(); 0370 for (; cur != end; cur++) { 0371 cur.value()->deref(); 0372 } 0373 } 0374 0375 bool CSSFontSelector::isEmpty() const 0376 { 0377 return false; 0378 //return m_fonts.isEmpty(); 0379 } 0380 0381 khtml::DocLoader *CSSFontSelector::docLoader() const 0382 { 0383 return m_document ? m_document->docLoader() : nullptr; 0384 } 0385 0386 void CSSFontSelector::addFontFaceRule(const CSSFontFaceRuleImpl *fontFaceRule) 0387 { 0388 // Obtain the font-family property and the src property. Both must be defined. 0389 const CSSStyleDeclarationImpl *style = fontFaceRule->style(); 0390 CSSValueImpl *fontFamily = style->getPropertyCSSValue(CSS_PROP_FONT_FAMILY); 0391 CSSValueImpl *src = style->getPropertyCSSValue(CSS_PROP_SRC); 0392 CSSValueImpl *unicodeRange = style->getPropertyCSSValue(CSS_PROP_UNICODE_RANGE); 0393 0394 if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList())) { 0395 return; 0396 } 0397 0398 CSSValueListImpl *familyList = static_cast<CSSValueListImpl *>(fontFamily); 0399 if (!familyList->length()) { 0400 return; 0401 } 0402 0403 CSSValueListImpl *srcList = static_cast<CSSValueListImpl *>(src); 0404 if (!srcList->length()) { 0405 return; 0406 } 0407 0408 // CSSValueListImpl* rangeList = static_cast<CSSValueListImpl*>(unicodeRange); 0409 0410 unsigned traitsMask = 0; 0411 /* 0412 if (CSSValueImpl* fontStyle = style->getPropertyCSSValue(CSS_PROP_FONT_STYLE)) { 0413 0414 if (fontStyle->isPrimitiveValue()) { 0415 CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma); 0416 list->append(fontStyle); 0417 fontStyle = list; 0418 } else if (!fontStyle->isValueList()) 0419 return; 0420 0421 CSSValueListImpl* styleList = static_cast<CSSValueListImpl*>(fontStyle); 0422 unsigned numStyles = styleList->length(); 0423 if (!numStyles) 0424 return; 0425 0426 for (unsigned i = 0; i < numStyles; ++i) { 0427 switch (static_cast<CSSPrimitiveValueImpl*>(styleList[i])->getIdent()) { 0428 case CSS_ALL: 0429 traitsMask |= FontStyleMask; 0430 break; 0431 case CSS_NORMAL: 0432 traitsMask |= FontStyleNormalMask; 0433 break; 0434 case CSS_ITALIC: 0435 case CSS_OBLIQUE: 0436 traitsMask |= FontStyleItalicMask; 0437 break; 0438 default: 0439 break; 0440 } 0441 } 0442 } else 0443 traitsMask |= FontStyleMask; 0444 0445 if (CSSValueImpl* fontWeight = style->getPropertyCSSValue(CSS_PROP_FONT_WEIGHT)) { 0446 if (fontWeight->isPrimitiveValue()) { 0447 CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma); 0448 list->append(fontWeight); 0449 fontWeight = list; 0450 } else if (!fontWeight->isValueList()) 0451 return; 0452 0453 CSSValueListImpl* weightList = static_cast<CSSValueListImpl*>(fontWeight); 0454 unsigned numWeights = weightList->length(); 0455 if (!numWeights) 0456 return; 0457 0458 for (unsigned i = 0; i < numWeights; ++i) { 0459 switch (static_cast<CSSPrimitiveValueImpl*>(weightList[i])->getIdent()) { 0460 case CSS_VAL_ALL: 0461 traitsMask |= FontWeightMask; 0462 break; 0463 case CSS_VAL_BOLDER: 0464 case CSS_VAL_BOLD: 0465 case CSS_VAL_700: 0466 traitsMask |= FontWeight700Mask; 0467 break; 0468 case CSS_VAL_NORMAL: 0469 case CSS_VAL_400: 0470 traitsMask |= FontWeight400Mask; 0471 break; 0472 case CSS_VAL_900: 0473 traitsMask |= FontWeight900Mask; 0474 break; 0475 case CSS_VAL_800: 0476 traitsMask |= FontWeight800Mask; 0477 break; 0478 case CSS_VAL_600: 0479 traitsMask |= FontWeight600Mask; 0480 break; 0481 case CSS_VAL_500: 0482 traitsMask |= FontWeight500Mask; 0483 break; 0484 case CSS_VAL_300: 0485 traitsMask |= FontWeight300Mask; 0486 break; 0487 case CSS_VAL_LIGHTER: 0488 case CSS_VAL_200: 0489 traitsMask |= FontWeight200Mask; 0490 break; 0491 case CSS_VAL_100: 0492 traitsMask |= FontWeight100Mask; 0493 break; 0494 default: 0495 break; 0496 } 0497 } 0498 } else 0499 traitsMask |= FontWeightMask; 0500 0501 if (CSSValueImpl* fontVariant = style->getPropertyCSSValue(CSS_PROP_FONT_VARIANT)) { 0502 if (fontVariant->isPrimitiveValue()) { 0503 CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma); 0504 list->append(fontVariant); 0505 fontVariant = list; 0506 } else if (!fontVariant->isValueList()) 0507 return; 0508 0509 CSSValueListImpl* variantList = static_cast<CSSValueListImpl*>(fontVariant); 0510 unsigned numVariants = variantList->length(); 0511 if (!numVariants) 0512 return; 0513 0514 for (unsigned i = 0; i < numVariants; ++i) { 0515 switch (static_cast<CSSPrimitiveValueImpl*>(variantList[i])->getIdent()) { 0516 case CSS_VAL_ALL: 0517 traitsMask |= FontVariantMask; 0518 break; 0519 case CSS_VAL_NORMAL: 0520 traitsMask |= FontVariantNormalMask; 0521 break; 0522 case CSS_VAL_SMALL_CAPS: 0523 traitsMask |= FontVariantSmallCapsMask; 0524 break; 0525 default: 0526 break; 0527 } 0528 } 0529 } else 0530 traitsMask |= FontVariantNormalMask; 0531 */ 0532 0533 // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. 0534 CSSFontFace *fontFace = nullptr; 0535 0536 const int srcLength = srcList->length(); 0537 0538 #if 0 0539 // ENABLE(SVG_FONTS) 0540 bool foundSVGFont = false; 0541 #endif 0542 for (int i = 0; i < srcLength; i++) { 0543 // An item in the list either specifies a string (local font name) or a URL (remote font to download). 0544 CSSFontFaceSrcValueImpl *item = static_cast<CSSFontFaceSrcValueImpl *>(srcList->item(i)); 0545 CSSFontFaceSource *source = nullptr; 0546 0547 #if 0 0548 // ENABLE(SVG_FONTS) 0549 foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); 0550 #endif 0551 0552 if (!item->isLocal()) { 0553 if (item->isSupportedFormat() && m_document) { 0554 source = new CSSFontFaceSource(item->resource(), true /*distant*/); 0555 #if 0 0556 // ENABLE(SVG_FONTS) 0557 if (foundSVGFont) { 0558 cachedFont->setSVGFont(true); 0559 } 0560 #endif 0561 } 0562 } else { 0563 source = new CSSFontFaceSource(item->resource()); 0564 } 0565 0566 if (source) { 0567 #if 0 0568 // ENABLE(SVG_FONTS) 0569 source->setSVGFontFaceElement(item->svgFontFaceElement()); 0570 #endif 0571 if (!fontFace) { 0572 fontFace = new CSSFontFace(static_cast<FontTraitsMask>(traitsMask), this); 0573 } 0574 fontFace->addSource(source); 0575 } 0576 } 0577 0578 if (!fontFace || !fontFace->isValid()) { 0579 delete fontFace; 0580 return; 0581 } 0582 0583 /* 0584 if (rangeList) { 0585 unsigned numRanges = rangeList->length(); 0586 for (unsigned i = 0; i < numRanges; i++) { 0587 CSSUnicodeRangeValueImpl* range = static_cast<CSSUnicodeRangeValueImpl*>(rangeList->item(i)); 0588 fontFace->addRange(range->from(), range->to()); 0589 } 0590 } 0591 */ 0592 0593 // Hash under every single family name. 0594 int familyLength = familyList->length(); 0595 for (int i = 0; i < familyLength; i++) { 0596 CSSPrimitiveValueImpl *item = static_cast<CSSPrimitiveValueImpl *>(familyList->item(i)); 0597 DOMString familyName; 0598 if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING) { 0599 familyName = DOMString(static_cast<FontFamilyValueImpl *>(item)->fontName()); 0600 } else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { 0601 // We need to use the raw text for all the generic family types, since @font-face is a way of actually 0602 // defining what font to use for those types. 0603 switch (item->getIdent()) { 0604 case CSS_VAL_SERIF: 0605 familyName = "-khtml-serif"; 0606 break; 0607 case CSS_VAL_SANS_SERIF: 0608 familyName = "-khtml-sans-serif"; 0609 break; 0610 case CSS_VAL_CURSIVE: 0611 familyName = "-khtml-cursive"; 0612 break; 0613 case CSS_VAL_FANTASY: 0614 familyName = "-khtml-fantasy"; 0615 break; 0616 case CSS_VAL_MONOSPACE: 0617 familyName = "-khtml-monospace"; 0618 break; 0619 default: 0620 break; 0621 } 0622 } 0623 0624 if (familyName.isEmpty()) { 0625 continue; 0626 } 0627 0628 fontFace->addFamilyName(familyName); 0629 m_locallyInstalledFontFaces.insertMulti(familyName.lower(), fontFace); 0630 fontFace->ref(); 0631 0632 #if 0 0633 // ENABLE(SVG_FONTS) 0634 // SVG allows several <font> elements with the same font-family, differing only 0635 // in ie. font-variant. Be sure to pick up the right one - in getFontData below. 0636 if (foundSVGFont && (traitsMask & FontVariantSmallCapsMask)) { 0637 familyName += "-webkit-svg-small-caps"; 0638 } 0639 #endif 0640 0641 /* 0642 Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(familyName); 0643 if (!familyFontFaces) { 0644 familyFontFaces = new Vector<RefPtr<CSSFontFace> >; 0645 m_fontFaces.set(familyName, familyFontFaces); 0646 0647 ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); 0648 Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFaces; 0649 0650 Vector<unsigned> locallyInstalledFontsTraitsMasks; 0651 fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks); 0652 unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size(); 0653 if (numLocallyInstalledFaces) { 0654 familyLocallyInstalledFaces = new Vector<RefPtr<CSSFontFace> >; 0655 m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces); 0656 0657 for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { 0658 RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i])); 0659 locallyInstalledFontFace->addSource(new CSSFontFaceSource(familyName)); 0660 ASSERT(locallyInstalledFontFace->isValid()); 0661 familyLocallyInstalledFaces->append(locallyInstalledFontFace); 0662 } 0663 } 0664 } 0665 0666 familyFontFaces->append(fontFace); 0667 */ 0668 } 0669 0670 // Should be impossible, but in case empty/invalid family name makes it through... 0671 if (fontFace->refCount() < 1) { 0672 delete fontFace; 0673 } 0674 } 0675 0676 void CSSFontSelector::requestFamilyName(const DOMString &familyName) 0677 { 0678 QHash<DOMString, CSSFontFace*>::const_iterator it = m_locallyInstalledFontFaces.constBegin(); 0679 QHash<DOMString, CSSFontFace*>::const_iterator end = m_locallyInstalledFontFaces.constEnd(); 0680 if (it == end) { 0681 return; 0682 } 0683 const DOMString familyNameLower = familyName.lower(); 0684 do { 0685 if (it.key() == familyNameLower) { 0686 it.value()->refLoaders(); 0687 } 0688 ++it; 0689 } while (it != end); 0690 } 0691 0692 void CSSFontSelector::fontLoaded() 0693 { 0694 if (!m_document || !m_document->renderer()) { 0695 return; 0696 } 0697 static_cast<khtml::RenderCanvas *>(m_document->renderer())->updateInvalidatedFonts(); 0698 khtml::Font::markAllCachedFontsAsValid(); 0699 } 0700 0701 void CSSFontSelector::fontCacheInvalidated() 0702 { 0703 if (!m_document || !m_document->renderer()) { 0704 return; 0705 } 0706 m_document->recalcStyle(DocumentImpl::Force); 0707 // m_document->renderer()->setNeedsLayoutAndMinMaxRecalc(); 0708 } 0709 0710 /* 0711 static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName) 0712 { 0713 if (!document || !document->frame()) 0714 return 0; 0715 0716 const Settings* settings = document->frame()->settings(); 0717 if (!settings) 0718 return 0; 0719 0720 AtomicString genericFamily; 0721 if (familyName == "-webkit-serif") 0722 genericFamily = settings->serifFontFamily(); 0723 else if (familyName == "-webkit-sans-serif") 0724 genericFamily = settings->sansSerifFontFamily(); 0725 else if (familyName == "-webkit-cursive") 0726 genericFamily = settings->cursiveFontFamily(); 0727 else if (familyName == "-webkit-fantasy") 0728 genericFamily = settings->fantasyFontFamily(); 0729 else if (familyName == "-webkit-monospace") 0730 genericFamily = settings->fixedFontFamily(); 0731 else if (familyName == "-webkit-standard") 0732 genericFamily = settings->standardFontFamily(); 0733 0734 if (!genericFamily.isEmpty()) 0735 return fontCache()->getCachedFontData(fontCache()->getCachedFontPlatformData(fontDescription, genericFamily)); 0736 0737 return 0; 0738 } 0739 */ 0740 static FontTraitsMask desiredTraitsMaskForComparison; 0741 0742 static inline bool compareFontFaces(CSSFontFace *first, CSSFontFace *second) 0743 { 0744 FontTraitsMask firstTraitsMask = first->traitsMask(); 0745 FontTraitsMask secondTraitsMask = second->traitsMask(); 0746 0747 bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparison & FontVariantMask; 0748 bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForComparison & FontVariantMask; 0749 0750 if (firstHasDesiredVariant != secondHasDesiredVariant) { 0751 return firstHasDesiredVariant; 0752 } 0753 0754 bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask; 0755 bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask; 0756 0757 if (firstHasDesiredStyle != secondHasDesiredStyle) { 0758 return firstHasDesiredStyle; 0759 } 0760 0761 if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask) { 0762 return false; 0763 } 0764 if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask) { 0765 return true; 0766 } 0767 0768 // https://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#q46 says: "If there are fewer then 9 weights in the family, the default algorithm 0769 // 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', 0770 // '700', '800', or '900' remains unassigned, they are assigned to the same face as the next darker assigned keyword, if any, or the next 0771 // lighter one otherwise. If any of '300', '200', or '100' remains unassigned, it is assigned to the next lighter assigned keyword, if any, 0772 // or the next darker otherwise." 0773 // For '400', we made up our own rule (which then '500' follows). 0774 0775 static const unsigned fallbackRuleSets = 9; 0776 static const unsigned rulesPerSet = 8; 0777 static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = { 0778 { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 0779 { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 0780 { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 0781 { FontWeight500Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask }, 0782 { FontWeight400Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask }, 0783 { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 0784 { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 0785 { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 0786 { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask } 0787 }; 0788 0789 unsigned ruleSetIndex = 0; 0790 unsigned w = FontWeight100Bit; 0791 while (!(desiredTraitsMaskForComparison & (1 << w))) { 0792 w++; 0793 ruleSetIndex++; 0794 } 0795 0796 assert(ruleSetIndex < fallbackRuleSets); 0797 const FontTraitsMask *weightFallbackRule = weightFallbackRuleSets[ruleSetIndex]; 0798 for (unsigned i = 0; i < rulesPerSet; ++i) { 0799 if (secondTraitsMask & weightFallbackRule[i]) { 0800 return false; 0801 } 0802 if (firstTraitsMask & weightFallbackRule[i]) { 0803 return true; 0804 } 0805 } 0806 0807 return false; 0808 } 0809 0810 /* 0811 FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName) 0812 { 0813 if (m_fontFaces.isEmpty()) { 0814 if (familyName.startsWith("-khtml-")) 0815 return fontDataForGenericFamily(m_document, fontDescription, familyName); 0816 return 0; 0817 } 0818 0819 String family = familyName.string(); 0820 0821 #if 0 0822 // ENABLE(SVG_FONTS) 0823 if (fontDescription.smallCaps()) 0824 family += "-khtml-svg-small-caps"; 0825 #endif 0826 0827 Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family); 0828 // If no face was found, then return 0 and let the OS come up with its best match for the name. 0829 if (!familyFontFaces || familyFontFaces->isEmpty()) { 0830 // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our 0831 // settings. 0832 return fontDataForGenericFamily(m_document, fontDescription, familyName); 0833 } 0834 0835 HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >* segmentedFontFaceCache = m_fonts.get(family); 0836 if (!segmentedFontFaceCache) { 0837 segmentedFontFaceCache = new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >; 0838 m_fonts.set(family, segmentedFontFaceCache); 0839 } 0840 0841 FontTraitsMask traitsMask = fontDescription.traitsMask(); 0842 0843 RefPtr<CSSSegmentedFontFace> face = segmentedFontFaceCache->get(traitsMask); 0844 0845 if (!face) { 0846 face = CSSSegmentedFontFace::create(this); 0847 segmentedFontFaceCache->set(traitsMask, face); 0848 // Collect all matching faces and sort them in order of preference. 0849 Vector<CSSFontFace*, 32> candidateFontFaces; 0850 for (int i = familyFontFaces->size() - 1; i >= 0; --i) { 0851 CSSFontFace* candidate = familyFontFaces->at(i).get(); 0852 unsigned candidateTraitsMask = candidate->traitsMask(); 0853 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) 0854 continue; 0855 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) 0856 continue; 0857 candidateFontFaces.append(candidate); 0858 } 0859 0860 if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) { 0861 unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size(); 0862 for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) { 0863 CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get(); 0864 unsigned candidateTraitsMask = candidate->traitsMask(); 0865 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) 0866 continue; 0867 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) 0868 continue; 0869 candidateFontFaces.append(candidate); 0870 } 0871 } 0872 0873 desiredTraitsMaskForComparison = traitsMask; 0874 std::stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces); 0875 unsigned numCandidates = candidateFontFaces.size(); 0876 for (unsigned i = 0; i < numCandidates; ++i) 0877 face->appendFontFace(candidateFontFaces[i]); 0878 } 0879 0880 // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. 0881 return face->getFontData(fontDescription); 0882 } 0883 */ 0884 0885 }