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 }