Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> | 3 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 traitsMask |= FontVariantSmallCapsMask; | 188 traitsMask |= FontVariantSmallCapsMask; |
| 189 break; | 189 break; |
| 190 default: | 190 default: |
| 191 break; | 191 break; |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 } else | 194 } else |
| 195 traitsMask |= FontVariantMask; | 195 traitsMask |= FontVariantMask; |
| 196 | 196 |
| 197 // Each item in the src property's list is a single CSSFontFaceSource. Put t hem all into a CSSFontFace. | 197 // Each item in the src property's list is a single CSSFontFaceSource. Put t hem all into a CSSFontFace. |
| 198 RefPtr<CSSFontFace> fontFace; | 198 Handle<CSSFontFace> fontFace; |
| 199 | 199 |
| 200 int srcLength = srcList->length(); | 200 int srcLength = srcList->length(); |
| 201 | 201 |
| 202 bool foundSVGFont = false; | 202 bool foundSVGFont = false; |
| 203 | 203 |
| 204 for (int i = 0; i < srcLength; i++) { | 204 for (int i = 0; i < srcLength; i++) { |
| 205 // An item in the list either specifies a string (local font name) or a URL (remote font to download). | 205 // An item in the list either specifies a string (local font name) or a URL (remote font to download). |
| 206 CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->i temWithoutBoundsCheck(i)); | 206 CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->i temWithoutBoundsCheck(i)); |
| 207 OwnPtr<CSSFontFaceSource> source; | 207 OwnPtr<CSSFontFaceSource> source; |
| 208 | 208 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 familyName = pictographFamily; | 285 familyName = pictographFamily; |
| 286 break; | 286 break; |
| 287 default: | 287 default: |
| 288 break; | 288 break; |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 if (familyName.isEmpty()) | 292 if (familyName.isEmpty()) |
| 293 continue; | 293 continue; |
| 294 | 294 |
| 295 OwnPtr<Vector<RefPtr<CSSFontFace> > >& familyFontFaces = m_fontFaces.add (familyName, nullptr).iterator->value; | 295 // FIXME(oilpan): This is dangerous because the below 'new' can trigger a GC and |
| 296 // some finalizer can get rid of the collection from m_fontFaces. | |
| 297 // Then subsequent access to familyFontFaces causes use-after-free. | |
| 298 // We should move the collection to the managed heap. | |
| 299 CSSFontFaceVectorCollection* familyFontFaces = m_fontFaces.add(familyNam e, nullptr).iterator->value.get(); | |
| 296 if (!familyFontFaces) { | 300 if (!familyFontFaces) { |
| 297 familyFontFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >); | 301 familyFontFaces = new CSSFontFaceVectorCollection; |
| 302 m_fontFaces.set(familyName, adoptPtr(familyFontFaces)); | |
| 298 | 303 |
| 299 ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); | 304 ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); |
| 300 | 305 |
| 301 Vector<unsigned> locallyInstalledFontsTraitsMasks; | 306 Vector<unsigned> locallyInstalledFontsTraitsMasks; |
| 302 fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTrai tsMasks); | 307 fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTrai tsMasks); |
| 303 if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsM asks.size()) { | 308 if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsM asks.size()) { |
| 304 OwnPtr<Vector<RefPtr<CSSFontFace> > > familyLocallyInstalledFace s = adoptPtr(new Vector<RefPtr<CSSFontFace> >); | 309 OwnPtr<CSSFontFaceVectorCollection> familyLocallyInstalledFaces = adoptPtr(new CSSFontFaceVectorCollection); |
| 305 | 310 |
| 306 for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { | 311 for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { |
| 307 RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace:: create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), nullptr , true); | 312 HandleScope scope; |
| 313 Handle<CSSFontFace> locallyInstalledFontFace = CSSFontFace:: create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), nullptr , true); | |
| 308 locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFace Source(familyName))); | 314 locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFace Source(familyName))); |
| 309 ASSERT(locallyInstalledFontFace->isValid()); | 315 ASSERT(locallyInstalledFontFace->isValid()); |
| 310 familyLocallyInstalledFaces->append(locallyInstalledFontFace ); | 316 (*familyLocallyInstalledFaces)->append(locallyInstalledFontF ace); |
| 311 } | 317 } |
| 312 | 318 |
| 313 m_locallyInstalledFontFaces.set(familyName, familyLocallyInstall edFaces.release()); | 319 m_locallyInstalledFontFaces.set(familyName, familyLocallyInstall edFaces.release()); |
| 314 } | 320 } |
| 315 } | 321 } |
| 316 | 322 |
| 317 familyFontFaces->append(fontFace); | 323 (*familyFontFaces)->append(fontFace); |
| 318 | 324 |
| 319 ++m_version; | 325 ++m_version; |
| 320 } | 326 } |
| 321 } | 327 } |
| 322 | 328 |
| 323 void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* clien t) | 329 void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* clien t) |
| 324 { | 330 { |
| 325 m_clients.add(client); | 331 m_clients.add(client); |
| 326 } | 332 } |
| 327 | 333 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 genericFamily = settings->standardFontFamily(script); | 391 genericFamily = settings->standardFontFamily(script); |
| 386 | 392 |
| 387 if (!genericFamily.isEmpty()) | 393 if (!genericFamily.isEmpty()) |
| 388 return fontCache()->getCachedFontData(fontDescription, genericFamily); | 394 return fontCache()->getCachedFontData(fontDescription, genericFamily); |
| 389 | 395 |
| 390 return 0; | 396 return 0; |
| 391 } | 397 } |
| 392 | 398 |
| 393 static FontTraitsMask desiredTraitsMaskForComparison; | 399 static FontTraitsMask desiredTraitsMaskForComparison; |
| 394 | 400 |
| 395 static inline bool compareFontFaces(CSSFontFace* first, CSSFontFace* second) | 401 static inline bool compareFontFaces(Handle<CSSFontFace> first, Handle<CSSFontFac e> second) |
| 396 { | 402 { |
| 397 FontTraitsMask firstTraitsMask = first->traitsMask(); | 403 FontTraitsMask firstTraitsMask = first->traitsMask(); |
| 398 FontTraitsMask secondTraitsMask = second->traitsMask(); | 404 FontTraitsMask secondTraitsMask = second->traitsMask(); |
| 399 | 405 |
| 400 bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparis on & FontVariantMask; | 406 bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparis on & FontVariantMask; |
| 401 bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForCompar ison & FontVariantMask; | 407 bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForCompar ison & FontVariantMask; |
| 402 | 408 |
| 403 if (firstHasDesiredVariant != secondHasDesiredVariant) | 409 if (firstHasDesiredVariant != secondHasDesiredVariant) |
| 404 return firstHasDesiredVariant; | 410 return firstHasDesiredVariant; |
| 405 | 411 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDes cription, const AtomicString& familyName) | 481 PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDes cription, const AtomicString& familyName) |
| 476 { | 482 { |
| 477 if (m_fontFaces.isEmpty()) { | 483 if (m_fontFaces.isEmpty()) { |
| 478 if (familyName.startsWith("-webkit-")) | 484 if (familyName.startsWith("-webkit-")) |
| 479 return fontDataForGenericFamily(m_document, fontDescription, familyN ame); | 485 return fontDataForGenericFamily(m_document, fontDescription, familyN ame); |
| 480 if (fontDescription.genericFamily() == FontDescription::StandardFamily & & !fontDescription.isSpecifiedFont()) | 486 if (fontDescription.genericFamily() == FontDescription::StandardFamily & & !fontDescription.isSpecifiedFont()) |
| 481 return fontDataForGenericFamily(m_document, fontDescription, "-webki t-standard"); | 487 return fontDataForGenericFamily(m_document, fontDescription, "-webki t-standard"); |
| 482 return 0; | 488 return 0; |
| 483 } | 489 } |
| 484 | 490 |
| 485 CSSSegmentedFontFace* face = getFontFace(fontDescription, familyName); | 491 Handle<CSSSegmentedFontFace> face = getFontFace(fontDescription, familyName) ; |
| 486 // If no face was found, then return 0 and let the OS come up with its best match for the name. | 492 // If no face was found, then return 0 and let the OS come up with its best match for the name. |
| 487 if (!face) { | 493 if (!face) { |
| 488 // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our | 494 // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our |
| 489 // settings. | 495 // settings. |
| 490 if (fontDescription.genericFamily() == FontDescription::StandardFamily & & !fontDescription.isSpecifiedFont()) | 496 if (fontDescription.genericFamily() == FontDescription::StandardFamily & & !fontDescription.isSpecifiedFont()) |
| 491 return fontDataForGenericFamily(m_document, fontDescription, "-webki t-standard"); | 497 return fontDataForGenericFamily(m_document, fontDescription, "-webki t-standard"); |
| 492 return fontDataForGenericFamily(m_document, fontDescription, familyName) ; | 498 return fontDataForGenericFamily(m_document, fontDescription, familyName) ; |
| 493 } | 499 } |
| 494 | 500 |
| 495 // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. | 501 // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. |
| 496 return face->getFontData(fontDescription); | 502 return face->getFontData(fontDescription); |
| 497 } | 503 } |
| 498 | 504 |
| 499 CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDe scription, const AtomicString& family) | 505 Result<CSSSegmentedFontFace> CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& family) |
| 500 { | 506 { |
| 501 Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family); | 507 CSSFontFaceVectorCollection* familyFontFaces = m_fontFaces.get(family); |
| 502 if (!familyFontFaces || familyFontFaces->isEmpty()) | 508 if (!familyFontFaces || (*familyFontFaces)->isEmpty()) |
| 503 return 0; | 509 return nullptr; |
| 504 | 510 |
| 505 OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFace Cache = m_fonts.add(family, nullptr).iterator->value; | 511 // FIXME(oilpan): This is dangerous because the below 'new' can trigger a GC and |
| 506 if (!segmentedFontFaceCache) | 512 // some finalizer can get rid of the hashmap from m_fonts. |
| 507 segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmen tedFontFace> >); | 513 // Then subsequent access to segmentedFontFaceCache causes use-after-free. |
| 514 // We should move the hashmap to the managed heap. | |
| 515 HashMap<unsigned, Persistent<CSSSegmentedFontFace> >* segmentedFontFaceCache = m_fonts.add(family, nullptr).iterator->value.get(); | |
| 516 if (!segmentedFontFaceCache) { | |
| 517 segmentedFontFaceCache = new HashMap<unsigned, Persistent<CSSSegmentedFo ntFace> >; | |
| 518 m_fonts.set(family, adoptPtr(segmentedFontFaceCache)); | |
| 519 } | |
| 508 | 520 |
| 509 FontTraitsMask traitsMask = fontDescription.traitsMask(); | 521 FontTraitsMask traitsMask = fontDescription.traitsMask(); |
| 510 | 522 |
| 511 RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).iterator->value; | 523 Handle<CSSSegmentedFontFace> face = segmentedFontFaceCache->add(traitsMask, nullptr).iterator->value; |
| 512 if (!face) { | 524 if (face) |
| 513 face = CSSSegmentedFontFace::create(this); | 525 return face; |
| 514 | 526 |
| 515 // Collect all matching faces and sort them in order of preference. | 527 face = CSSSegmentedFontFace::create(this); |
| 516 Vector<CSSFontFace*, 32> candidateFontFaces; | 528 segmentedFontFaceCache->set(traitsMask, face); |
| 517 for (int i = familyFontFaces->size() - 1; i >= 0; --i) { | 529 |
| 518 CSSFontFace* candidate = familyFontFaces->at(i).get(); | 530 // Collect all matching faces and sort them in order of preference. |
| 531 Vector<Handle<CSSFontFace>, 32> candidateFontFaces; | |
|
haraken
2013/07/03 12:03:23
This is wrong. Handles in the vector are freed in
Mads Ager (google)
2013/07/03 12:18:38
Yes, good catch.
| |
| 532 for (int i = (*familyFontFaces)->size() - 1; i >= 0; --i) { | |
| 533 HandleScope scope; | |
| 534 Handle<CSSFontFace> candidate = (*familyFontFaces)->at(i); | |
| 535 unsigned candidateTraitsMask = candidate->traitsMask(); | |
| 536 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontSt yleNormalMask)) | |
| 537 continue; | |
| 538 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & Font VariantNormalMask)) | |
| 539 continue; | |
| 540 #if ENABLE(SVG_FONTS) | |
| 541 // For SVG Fonts that specify that they only support the "normal" varian t, we will assume they are incapable | |
| 542 // of small-caps synthesis and just ignore the font face as a candidate. | |
| 543 if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallC apsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask)) | |
| 544 continue; | |
| 545 #endif | |
| 546 candidateFontFaces.append(candidate); | |
| 547 } | |
| 548 | |
| 549 CSSFontFaceVectorCollection* familyLocallyInstalledFontFaces = m_locallyInst alledFontFaces.get(family); | |
| 550 if (familyLocallyInstalledFontFaces) { | |
| 551 unsigned numLocallyInstalledFontFaces = (*familyLocallyInstalledFontFace s)->size(); | |
| 552 for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) { | |
| 553 Handle<CSSFontFace> candidate = (*familyLocallyInstalledFontFaces)-> at(i); | |
| 519 unsigned candidateTraitsMask = candidate->traitsMask(); | 554 unsigned candidateTraitsMask = candidate->traitsMask(); |
| 520 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & Fo ntStyleNormalMask)) | 555 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & Fo ntStyleNormalMask)) |
| 521 continue; | 556 continue; |
| 522 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) | 557 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) |
| 523 continue; | 558 continue; |
| 524 #if ENABLE(SVG_FONTS) | |
| 525 // For SVG Fonts that specify that they only support the "normal" va riant, we will assume they are incapable | |
| 526 // of small-caps synthesis and just ignore the font face as a candid ate. | |
| 527 if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSm allCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask)) | |
| 528 continue; | |
| 529 #endif | |
| 530 candidateFontFaces.append(candidate); | 559 candidateFontFaces.append(candidate); |
| 531 } | 560 } |
| 561 } | |
| 532 | 562 |
| 533 if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_lo callyInstalledFontFaces.get(family)) { | 563 desiredTraitsMaskForComparison = traitsMask; |
| 534 unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFa ces->size(); | 564 stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFon tFaces); |
| 535 for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) { | 565 unsigned numCandidates = candidateFontFaces.size(); |
| 536 CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i). get(); | 566 for (unsigned i = 0; i < numCandidates; ++i) |
| 537 unsigned candidateTraitsMask = candidate->traitsMask(); | 567 face->appendFontFace(candidateFontFaces[i]); |
| 538 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) | 568 return face; |
| 539 continue; | |
| 540 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMas k & FontVariantNormalMask)) | |
| 541 continue; | |
| 542 candidateFontFaces.append(candidate); | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 desiredTraitsMaskForComparison = traitsMask; | |
| 547 stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compar eFontFaces); | |
| 548 unsigned numCandidates = candidateFontFaces.size(); | |
| 549 for (unsigned i = 0; i < numCandidates; ++i) | |
| 550 face->appendFontFace(candidateFontFaces[i]); | |
| 551 } | |
| 552 return face.get(); | |
| 553 } | 569 } |
| 554 | 570 |
| 555 void CSSFontSelector::clearDocument() | 571 void CSSFontSelector::clearDocument() |
| 556 { | 572 { |
| 557 if (!m_document) { | 573 if (!m_document) { |
| 558 ASSERT(!m_beginLoadingTimer.isActive()); | 574 ASSERT(!m_beginLoadingTimer.isActive()); |
| 559 ASSERT(m_fontsToBeginLoading.isEmpty()); | 575 ASSERT(m_fontsToBeginLoading.isEmpty()); |
| 560 return; | 576 return; |
| 561 } | 577 } |
| 562 | 578 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 } | 618 } |
| 603 // Ensure that if the request count reaches zero, the frame loader will know about it. | 619 // Ensure that if the request count reaches zero, the frame loader will know about it. |
| 604 cachedResourceLoader->loadDone(0); | 620 cachedResourceLoader->loadDone(0); |
| 605 // New font loads may be triggered by layout after the document load is comp lete but before we have dispatched | 621 // New font loads may be triggered by layout after the document load is comp lete but before we have dispatched |
| 606 // didFinishLoading for the frame. Make sure the delegate is always dispatch ed by checking explicitly. | 622 // didFinishLoading for the frame. Make sure the delegate is always dispatch ed by checking explicitly. |
| 607 if (m_document && m_document->frame()) | 623 if (m_document && m_document->frame()) |
| 608 m_document->frame()->loader()->checkLoadComplete(); | 624 m_document->frame()->loader()->checkLoadComplete(); |
| 609 } | 625 } |
| 610 | 626 |
| 611 } | 627 } |
| OLD | NEW |