fast/forms/text-control-intrinsic-widths.html fails on Mac if Word/Office fonts are...
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Sep 2011 22:53:53 +0000 (22:53 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Sep 2011 22:53:53 +0000 (22:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=35273

Reviewed by Dan Bernstein.

There are two types of font issue that can cause layout test failure.
First, the user may have non-standard fonts installed that affect the layout
of some tests. For example, some tests use the MS Gothic font if installed.

Secondly, the user may have duplicate fonts installed in ~/Library/Fonts,
which override the system fonts (e.g. a copy of Arial from MS Office). For
some tests, this can affect font metrics or fallback behavior.

This change addresses the first problem only. It limits the set of fonts
available through NSFontManager, by swizzling some methods to return
a list of fonts or font families which only include fonts from a hardcoded
whitelist.

* DumpRenderTree/mac/DumpRenderTree.mm:
(allowedFontFamilySet):
(drt_NSFontManager_availableFontFamilies):
(drt_NSFontManager_availableFonts):
(swizzleNSFontManagerMethods):
(activateTestingFonts):
(adjustFonts):
(createWebViewAndOffscreenWindow):
(prepareConsistentTestingEnvironment):
* WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm:
(WTR::allowedFontFamilySet):
(WTR::drt_NSFontManager_availableFontFamilies):
(WTR::drt_NSFontManager_availableFonts):
(WTR::swizzleNSFontManagerMethods):
(WTR::InjectedBundle::platformInitialize):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@96434 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/DumpRenderTree/mac/DumpRenderTree.mm
Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm

index fab144dc173beaafba4004ff09cd004e86bee80b..5102099111281ccad6a62006b9272a674b8bd3ef 100644 (file)
@@ -1,3 +1,39 @@
+2011-09-30  Simon Fraser  <simon.fraser@apple.com>
+
+        fast/forms/text-control-intrinsic-widths.html fails on Mac if Word/Office fonts are installed
+        https://bugs.webkit.org/show_bug.cgi?id=35273
+
+        Reviewed by Dan Bernstein.
+        
+        There are two types of font issue that can cause layout test failure.
+        First, the user may have non-standard fonts installed that affect the layout
+        of some tests. For example, some tests use the MS Gothic font if installed.
+        
+        Secondly, the user may have duplicate fonts installed in ~/Library/Fonts,
+        which override the system fonts (e.g. a copy of Arial from MS Office). For
+        some tests, this can affect font metrics or fallback behavior.
+        
+        This change addresses the first problem only. It limits the set of fonts
+        available through NSFontManager, by swizzling some methods to return
+        a list of fonts or font families which only include fonts from a hardcoded
+        whitelist.
+        
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (allowedFontFamilySet):
+        (drt_NSFontManager_availableFontFamilies):
+        (drt_NSFontManager_availableFonts):
+        (swizzleNSFontManagerMethods):
+        (activateTestingFonts):
+        (adjustFonts):
+        (createWebViewAndOffscreenWindow):
+        (prepareConsistentTestingEnvironment):
+        * WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm:
+        (WTR::allowedFontFamilySet):
+        (WTR::drt_NSFontManager_availableFontFamilies):
+        (WTR::drt_NSFontManager_availableFonts):
+        (WTR::swizzleNSFontManagerMethods):
+        (WTR::InjectedBundle::platformInitialize):
+
 2011-09-30  David Levin  <levin@chromium.org>
 
         Need to skip webkitpy.common.checkout.baselineoptimizer_unittest.BaselineOptimizerTest on Windows..
index 207b421b2db5ac6f5033a268c276d61c65081627..c357c3c813d65f9461c29791cb3eb609e7a59c71 100644 (file)
@@ -221,41 +221,187 @@ static bool shouldIgnoreWebCoreNodeLeaks(const string& URLString)
     return false;
 }
 
-static void activateFonts()
+static NSSet *allowedFontFamilySet()
 {
-#ifdef BUILDING_ON_LEOPARD
-    static const char* fontSectionNames[] = {
-        "Ahem",
-        "WeightWatcher100",
-        "WeightWatcher200",
-        "WeightWatcher300",
-        "WeightWatcher400",
-        "WeightWatcher500",
-        "WeightWatcher600",
-        "WeightWatcher700",
-        "WeightWatcher800",
-        "WeightWatcher900",
-        0
-    };
+    static NSSet *fontFamiliySet = [[NSSet setWithObjects:
+        @"Ahem",
+        @"Al Bayan",
+        @"American Typewriter",
+        @"Andale Mono",
+        @"Apple Braille",
+        @"Apple Color Emoji",
+        @"Apple Chancery",
+        @"Apple Garamond BT",
+        @"Apple LiGothic",
+        @"Apple LiSung",
+        @"Apple Symbols",
+        @"AppleGothic",
+        @"AppleMyungjo",
+        @"Arial Black",
+        @"Arial Hebrew",
+        @"Arial Narrow",
+        @"Arial Rounded MT Bold",
+        @"Arial Unicode MS",
+        @"Arial",
+        @"Ayuthaya",
+        @"Baghdad",
+        @"Baskerville",
+        @"BiauKai",
+        @"Big Caslon",
+        @"Brush Script MT",
+        @"Chalkboard",
+        @"Chalkduster",
+        @"Charcoal CY",
+        @"Cochin",
+        @"ColorBits",
+        @"Comic Sans MS",
+        @"Copperplate",
+        @"Corsiva Hebrew",
+        @"Courier New",
+        @"Courier",
+        @"DecoType Naskh",
+        @"Devanagari MT",
+        @"Didot",
+        @"Euphemia UCAS",
+        @"Futura",
+        @"GB18030 Bitmap",
+        @"Geeza Pro",
+        @"Geneva CY",
+        @"Geneva",
+        @"Georgia",
+        @"Gill Sans",
+        @"Gujarati MT",
+        @"GungSeo",
+        @"Gurmukhi MT",
+        @"HeadLineA",
+        @"Hei",
+        @"Heiti SC",
+        @"Heiti TC",
+        @"Helvetica CY",
+        @"Helvetica Neue",
+        @"Helvetica",
+        @"Herculanum",
+        @"Hiragino Kaku Gothic Pro",
+        @"Hiragino Kaku Gothic ProN",
+        @"Hiragino Kaku Gothic Std",
+        @"Hiragino Kaku Gothic StdN",
+        @"Hiragino Maru Gothic Pro",
+        @"Hiragino Maru Gothic ProN",
+        @"Hiragino Mincho Pro",
+        @"Hiragino Mincho ProN",
+        @"Hiragino Sans GB",
+        @"Hoefler Text",
+        @"Impact",
+        @"InaiMathi",
+        @"Kai",
+        @"Kailasa",
+        @"Kokonor",
+        @"Krungthep",
+        @"KufiStandardGK",
+        @"LiHei Pro",
+        @"LiSong Pro",
+        @"Lucida Grande",
+        @"Marker Felt",
+        @"Menlo",
+        @"Microsoft Sans Serif",
+        @"Monaco",
+        @"Mshtakan",
+        @"Nadeem",
+        @"New Peninim MT",
+        @"Optima",
+        @"Osaka",
+        @"Papyrus",
+        @"PCMyungjo",
+        @"PilGi",
+        @"Plantagenet Cherokee",
+        @"Raanana",
+        @"Sathu",
+        @"Silom",
+        @"Skia",
+        @"STFangsong",
+        @"STHeiti",
+        @"STKaiti",
+        @"STSong",
+        @"Symbol",
+        @"Tahoma",
+        @"Thonburi",
+        @"Times New Roman",
+        @"Times",
+        @"Trebuchet MS",
+        @"Verdana",
+        @"Webdings",
+        @"WebKit WeightWatcher",
+        @"Wingdings 2",
+        @"Wingdings 3",
+        @"Wingdings",
+        @"Zapf Dingbats",
+        @"Zapfino",
+        nil] retain];
+    
+    return fontFamiliySet;
+}
 
-    for (unsigned i = 0; fontSectionNames[i]; ++i) {
-        unsigned long fontDataLength;
-        char* fontData = getsectdata("__DATA", fontSectionNames[i], &fontDataLength);
-        if (!fontData) {
-            fprintf(stderr, "Failed to locate the %s font.\n", fontSectionNames[i]);
-            exit(1);
-        }
+static IMP appKitAvailableFontFamiliesIMP;
+static IMP appKitAvailableFontsIMP;
+
+static NSArray *drt_NSFontManager_availableFontFamilies(id self, SEL _cmd)
+{
+    static NSArray *availableFontFamilies;
+    if (availableFontFamilies)
+        return availableFontFamilies;
+    
+    NSArray *availableFamilies = appKitAvailableFontFamiliesIMP(self, _cmd);
 
-        ATSFontContainerRef fontContainer;
-        OSStatus status = ATSFontActivateFromMemory(fontData, fontDataLength, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &fontContainer);
+    NSMutableSet *prunedFamiliesSet = [NSMutableSet setWithArray:availableFamilies];
+    [prunedFamiliesSet intersectSet:allowedFontFamilySet()];
 
-        if (status != noErr) {
-            fprintf(stderr, "Failed to activate the %s font.\n", fontSectionNames[i]);
-            exit(1);
+    availableFontFamilies = [[prunedFamiliesSet allObjects] retain];
+    return availableFontFamilies;
+}
+
+static NSArray *drt_NSFontManager_availableFonts(id self, SEL _cmd)
+{
+    static NSArray *availableFonts;
+    if (availableFonts)
+        return availableFonts;
+    
+    NSSet *allowedFamilies = allowedFontFamilySet();
+    NSMutableArray *availableFontList = [[NSMutableArray alloc] initWithCapacity:[allowedFamilies count] * 2];
+    for (NSString *fontFamily in allowedFontFamilySet()) {
+        NSArray* fontsForFamily = [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily];
+        for (NSArray* fontInfo in fontsForFamily) {
+            // Font name is the first entry in the array.
+            [availableFontList addObject:[fontInfo objectAtIndex:0]];
         }
     }
-#else
+    
+    availableFonts = availableFontList;
+    return availableFonts;
+}
+
+static void swizzleNSFontManagerMethods()
+{
+    Method availableFontFamiliesMethod = class_getInstanceMethod(objc_getClass("NSFontManager"), @selector(availableFontFamilies));
+    ASSERT(availableFontFamiliesMethod);
+    if (!availableFontFamiliesMethod) {
+        NSLog(@"Failed to swizzle the \"availableFontFamilies\" method on NSFontManager");
+        return;
+    }
+    
+    appKitAvailableFontFamiliesIMP = method_setImplementation(availableFontFamiliesMethod, (IMP)drt_NSFontManager_availableFontFamilies);
+
+    Method availableFontsMethod = class_getInstanceMethod(objc_getClass("NSFontManager"), @selector(availableFonts));
+    ASSERT(availableFontsMethod);
+    if (!availableFontsMethod) {
+        NSLog(@"Failed to swizzle the \"availableFonts\" method on NSFontManager");
+        return;
+    }
+    
+    appKitAvailableFontsIMP = method_setImplementation(availableFontsMethod, (IMP)drt_NSFontManager_availableFonts);
+}
 
+static void activateTestingFonts()
+{
     // Work around <rdar://problem/6698023> by activating fonts from disk
     // FIXME: This code can be removed once <rdar://problem/6698023> is addressed.
 
@@ -287,7 +433,12 @@ static void activateFonts()
         CFRelease(errors);
         exit(1);
     }
-#endif
+}
+
+static void adjustFonts()
+{
+    swizzleNSFontManagerMethods();
+    activateTestingFonts();
 }
 
 WebView *createWebViewAndOffscreenWindow()
@@ -317,10 +468,7 @@ WebView *createWebViewAndOffscreenWindow()
     NSRect windowRect = NSOffsetRect(rect, -10000, [(NSScreen *)[[NSScreen screens] objectAtIndex:0] frame].size.height - rect.size.height + 10000);
     DumpRenderTreeWindow *window = [[DumpRenderTreeWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
 
-#ifndef BUILDING_ON_LEOPARD
     [window setColorSpace:[[NSScreen mainScreen] colorSpace]];
-#endif
-
     [[window contentView] addSubview:webView];
     [window orderBack:nil];
     [window setAutodisplay:NO];
@@ -601,7 +749,7 @@ static void prepareConsistentTestingEnvironment()
     poseAsClass("DumpRenderTreeEvent", "NSEvent");
 
     setDefaultsToConsistentValuesForTesting();
-    activateFonts();
+    adjustFonts();
     
     if (dumpPixels)
         setupMainDisplayColorProfile();
index 15f82a1195c15bc6e0a6f4dae92735b29db52288..5ab6bda7e351078c050b8c19111331e98758e5b3 100644 (file)
 
 #import "InjectedBundle.h"
 
+#import <AppKit/AppKit.h>
 #import <Foundation/Foundation.h>
+#import <objc/objc-runtime.h>
 
 namespace WTR {
 
+static NSSet *allowedFontFamilySet()
+{
+    static NSSet *fontFamiliySet = [[NSSet setWithObjects:
+        @"Ahem",
+        @"Al Bayan",
+        @"American Typewriter",
+        @"Andale Mono",
+        @"Apple Braille",
+        @"Apple Color Emoji",
+        @"Apple Chancery",
+        @"Apple Garamond BT",
+        @"Apple LiGothic",
+        @"Apple LiSung",
+        @"Apple Symbols",
+        @"AppleGothic",
+        @"AppleMyungjo",
+        @"Arial Black",
+        @"Arial Hebrew",
+        @"Arial Narrow",
+        @"Arial Rounded MT Bold",
+        @"Arial Unicode MS",
+        @"Arial",
+        @"Ayuthaya",
+        @"Baghdad",
+        @"Baskerville",
+        @"BiauKai",
+        @"Big Caslon",
+        @"Brush Script MT",
+        @"Chalkboard",
+        @"Chalkduster",
+        @"Charcoal CY",
+        @"Cochin",
+        @"ColorBits",
+        @"Comic Sans MS",
+        @"Copperplate",
+        @"Corsiva Hebrew",
+        @"Courier New",
+        @"Courier",
+        @"DecoType Naskh",
+        @"Devanagari MT",
+        @"Didot",
+        @"Euphemia UCAS",
+        @"Futura",
+        @"GB18030 Bitmap",
+        @"Geeza Pro",
+        @"Geneva CY",
+        @"Geneva",
+        @"Georgia",
+        @"Gill Sans",
+        @"Gujarati MT",
+        @"GungSeo",
+        @"Gurmukhi MT",
+        @"HeadLineA",
+        @"Hei",
+        @"Heiti SC",
+        @"Heiti TC",
+        @"Helvetica CY",
+        @"Helvetica Neue",
+        @"Helvetica",
+        @"Herculanum",
+        @"Hiragino Kaku Gothic Pro",
+        @"Hiragino Kaku Gothic ProN",
+        @"Hiragino Kaku Gothic Std",
+        @"Hiragino Kaku Gothic StdN",
+        @"Hiragino Maru Gothic Pro",
+        @"Hiragino Maru Gothic ProN",
+        @"Hiragino Mincho Pro",
+        @"Hiragino Mincho ProN",
+        @"Hiragino Sans GB",
+        @"Hoefler Text",
+        @"Impact",
+        @"InaiMathi",
+        @"Kai",
+        @"Kailasa",
+        @"Kokonor",
+        @"Krungthep",
+        @"KufiStandardGK",
+        @"LiHei Pro",
+        @"LiSong Pro",
+        @"Lucida Grande",
+        @"Marker Felt",
+        @"Menlo",
+        @"Microsoft Sans Serif",
+        @"Monaco",
+        @"Mshtakan",
+        @"Nadeem",
+        @"New Peninim MT",
+        @"Optima",
+        @"Osaka",
+        @"Papyrus",
+        @"PCMyungjo",
+        @"PilGi",
+        @"Plantagenet Cherokee",
+        @"Raanana",
+        @"Sathu",
+        @"Silom",
+        @"Skia",
+        @"STFangsong",
+        @"STHeiti",
+        @"STKaiti",
+        @"STSong",
+        @"Symbol",
+        @"Tahoma",
+        @"Thonburi",
+        @"Times New Roman",
+        @"Times",
+        @"Trebuchet MS",
+        @"Verdana",
+        @"Webdings",
+        @"WebKit WeightWatcher",
+        @"Wingdings 2",
+        @"Wingdings 3",
+        @"Wingdings",
+        @"Zapf Dingbats",
+        @"Zapfino",
+        nil] retain];
+    
+    return fontFamiliySet;
+}
+
+static IMP appKitAvailableFontFamiliesIMP;
+static IMP appKitAvailableFontsIMP;
+
+static NSArray *drt_NSFontManager_availableFontFamilies(id self, SEL _cmd)
+{
+    static NSArray *availableFontFamilies;
+    if (availableFontFamilies)
+        return availableFontFamilies;
+    
+    NSArray *availableFamilies = appKitAvailableFontFamiliesIMP(self, _cmd);
+
+    NSMutableSet *prunedFamiliesSet = [NSMutableSet setWithArray:availableFamilies];
+    [prunedFamiliesSet intersectSet:allowedFontFamilySet()];
+
+    availableFontFamilies = [[prunedFamiliesSet allObjects] retain];
+    return availableFontFamilies;
+}
+
+static NSArray *drt_NSFontManager_availableFonts(id self, SEL _cmd)
+{
+    static NSArray *availableFonts;
+    if (availableFonts)
+        return availableFonts;
+    
+    NSSet *allowedFamilies = allowedFontFamilySet();
+    NSMutableArray *availableFontList = [[NSMutableArray alloc] initWithCapacity:[allowedFamilies count] * 2];
+    for (NSString *fontFamily in allowedFontFamilySet()) {
+        NSArray* fontsForFamily = [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily];
+        for (NSArray* fontInfo in fontsForFamily) {
+            // Font name is the first entry in the array.
+            [availableFontList addObject:[fontInfo objectAtIndex:0]];
+        }
+    }
+    
+    availableFonts = availableFontList;
+    return availableFonts;
+}
+
+static void swizzleNSFontManagerMethods()
+{
+    Method availableFontFamiliesMethod = class_getInstanceMethod(objc_getClass("NSFontManager"), @selector(availableFontFamilies));
+    ASSERT(availableFontFamiliesMethod);
+    if (!availableFontFamiliesMethod) {
+        NSLog(@"Failed to swizzle the \"availableFontFamilies\" method on NSFontManager");
+        return;
+    }
+    
+    appKitAvailableFontFamiliesIMP = method_setImplementation(availableFontFamiliesMethod, (IMP)drt_NSFontManager_availableFontFamilies);
+
+    Method availableFontsMethod = class_getInstanceMethod(objc_getClass("NSFontManager"), @selector(availableFonts));
+    ASSERT(availableFontsMethod);
+    if (!availableFontsMethod) {
+        NSLog(@"Failed to swizzle the \"availableFonts\" method on NSFontManager");
+        return;
+    }
+    
+    appKitAvailableFontsIMP = method_setImplementation(availableFontsMethod, (IMP)drt_NSFontManager_availableFonts);
+}
+
 void InjectedBundle::platformInitialize(WKTypeRef)
 {
     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@@ -40,6 +221,8 @@ void InjectedBundle::platformInitialize(WKTypeRef)
         nil];
 
     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+    
+    swizzleNSFontManagerMethods();
 }
 
 } // namespace WTR