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