diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/platform/graphics/mac/FontCacheMac.mm | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/platform/graphics/mac/FontCacheMac.mm')
-rw-r--r-- | Source/WebCore/platform/graphics/mac/FontCacheMac.mm | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm new file mode 100644 index 0000000..068bd8e --- /dev/null +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "FontCache.h" + +#import "Font.h" +#import "SimpleFontData.h" +#import "FontPlatformData.h" +#import "WebCoreSystemInterface.h" +#import "WebFontCache.h" +#import <AppKit/AppKit.h> +#import <wtf/StdLibExtras.h> + +#ifdef BUILDING_ON_TIGER +typedef int NSInteger; +#endif + +namespace WebCore { + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void *, CFDictionaryRef) +{ + ASSERT_UNUSED(observer, observer == fontCache()); + ASSERT_UNUSED(name, CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)); + fontCache()->invalidate(); +} +#else +static void fontCacheATSNotificationCallback(ATSFontNotificationInfoRef, void*) +{ + fontCache()->invalidate(); +} +#endif + +void FontCache::platformInit() +{ + wkSetUpFontCache(); +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately); +#else + // kCTFontManagerRegisteredFontsChangedNotification does not exist on Leopard and earlier. + // FIXME: Passing kATSFontNotifyOptionReceiveWhileSuspended may be an overkill and does not seem to work anyway. + ATSFontNotificationSubscribe(fontCacheATSNotificationCallback, kATSFontNotifyOptionReceiveWhileSuspended, 0, 0); +#endif +} + +static int toAppKitFontWeight(FontWeight fontWeight) +{ + static int appKitFontWeights[] = { + 2, // FontWeight100 + 3, // FontWeight200 + 4, // FontWeight300 + 5, // FontWeight400 + 6, // FontWeight500 + 8, // FontWeight600 + 9, // FontWeight700 + 10, // FontWeight800 + 12, // FontWeight900 + }; + return appKitFontWeights[fontWeight]; +} + +static inline bool isAppKitFontWeightBold(NSInteger appKitFontWeight) +{ + return appKitFontWeight >= 7; +} + +const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +{ + const FontPlatformData& platformData = font.fontDataAt(0)->fontDataForCharacter(characters[0])->platformData(); + NSFont *nsFont = platformData.font(); + + NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(characters) length:length freeWhenDone:NO]; + NSFont *substituteFont = wkGetFontInLanguageForRange(nsFont, string, NSMakeRange(0, length)); + [string release]; + + if (!substituteFont && length == 1) + substituteFont = wkGetFontInLanguageForCharacter(nsFont, characters[0]); + if (!substituteFont) + return 0; + + // Use the family name from the AppKit-supplied substitute font, requesting the + // traits, weight, and size we want. One way this does better than the original + // AppKit request is that it takes synthetic bold and oblique into account. + // But it does create the possibility that we could end up with a font that + // doesn't actually cover the characters we need. + + NSFontManager *fontManager = [NSFontManager sharedFontManager]; + + NSFontTraitMask traits; + NSInteger weight; + CGFloat size; + + if (nsFont) { + traits = [fontManager traitsOfFont:nsFont]; + if (platformData.m_syntheticBold) + traits |= NSBoldFontMask; + if (platformData.m_syntheticOblique) + traits |= NSFontItalicTrait; + weight = [fontManager weightOfFont:nsFont]; + size = [nsFont pointSize]; + } else { + // For custom fonts nsFont is nil. + traits = font.italic() ? NSFontItalicTrait : 0; + weight = toAppKitFontWeight(font.weight()); + size = font.pixelSize(); + } + + if (NSFont *bestVariation = [fontManager fontWithFamily:[substituteFont familyName] traits:traits weight:weight size:size]) + substituteFont = bestVariation; + + substituteFont = font.fontDescription().usePrinterFont() ? [substituteFont printerFont] : [substituteFont screenFont]; + + NSFontTraitMask substituteFontTraits = [fontManager traitsOfFont:substituteFont]; + NSInteger substituteFontWeight = [fontManager weightOfFont:substituteFont]; + + FontPlatformData alternateFont(substituteFont, platformData.size(), + !font.isPlatformFont() && isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight), + !font.isPlatformFont() && (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait), + platformData.m_orientation); + return getCachedFontData(&alternateFont); +} + +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +{ + // Attempt to find an appropriate font using a match based on + // the presence of keywords in the the requested names. For example, we'll + // match any name that contains "Arabic" to Geeza Pro. + SimpleFontData* simpleFontData = 0; + const FontFamily* currFamily = &font.fontDescription().family(); + while (currFamily && !simpleFontData) { + if (currFamily->family().length()) { + static String* matchWords[3] = { new String("Arabic"), new String("Pashto"), new String("Urdu") }; + DEFINE_STATIC_LOCAL(AtomicString, geezaStr, ("Geeza Pro")); + for (int j = 0; j < 3 && !simpleFontData; ++j) + if (currFamily->family().contains(*matchWords[j], false)) + simpleFontData = getCachedFontData(font.fontDescription(), geezaStr); + } + currFamily = currFamily->next(); + } + + return simpleFontData; +} + +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +{ + DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times")); + + // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick + // the default that the user would get without changing any prefs. + SimpleFontData* simpleFontData = getCachedFontData(fontDescription, timesStr); + if (simpleFontData) + return simpleFontData; + + // The Times fallback will almost always work, but in the highly unusual case where + // the user doesn't have it, we fall back on Lucida Grande because that's + // guaranteed to be there, according to Nathan Taylor. This is good enough + // to avoid a crash at least. + DEFINE_STATIC_LOCAL(AtomicString, lucidaGrandeStr, ("Lucida Grande")); + return getCachedFontData(fontDescription, lucidaGrandeStr); +} + +void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) +{ + [WebFontCache getTraits:traitsMasks inFamily:familyName]; +} + +FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) +{ + NSFontTraitMask traits = fontDescription.italic() ? NSFontItalicTrait : 0; + NSInteger weight = toAppKitFontWeight(fontDescription.weight()); + float size = fontDescription.computedPixelSize(); + + NSFont *nsFont = [WebFontCache fontWithFamily:family traits:traits weight:weight size:size]; + if (!nsFont) + return 0; + + NSFontManager *fontManager = [NSFontManager sharedFontManager]; + NSFontTraitMask actualTraits = 0; + if (fontDescription.italic()) + actualTraits = [fontManager traitsOfFont:nsFont]; + NSInteger actualWeight = [fontManager weightOfFont:nsFont]; + + NSFont *platformFont = fontDescription.usePrinterFont() ? [nsFont printerFont] : [nsFont screenFont]; + bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight); + bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait); + + return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation()); +} + +} // namespace WebCore |