18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Alexey Proskuryakov
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "config.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "SimpleFontData.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "BlockExceptions.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Color.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "FloatRect.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Font.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "FontCache.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "FontDescription.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "SharedBuffer.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebCoreSystemInterface.h"
418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#import <AppKit/AppKit.h>
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <ApplicationServices/ApplicationServices.h>
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <float.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <unicode/uchar.h>
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <wtf/Assertions.h>
46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#import <wtf/StdLibExtras.h>
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <wtf/RetainPtr.h>
4821939df44de1705786c545cd1bf519d47250322dBen Murdoch#import <wtf/UnusedParam.h>
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@interface NSFont (WebAppKitSecretAPI)
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)_isFakeFixedPitch;
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockusing namespace std;
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst float smallCapsFontSizeMultiplier = 0.7f;
59d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x / unitsPerEm; }
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool initFontData(SimpleFontData* fontData)
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!fontData->platformData().cgFont())
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSUStyle fontStyle;
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ATSUCreateStyle(&fontStyle) != noErr)
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ATSUFontID fontId = fontData->platformData().m_atsuFontID;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!fontId) {
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ATSUDisposeStyle(fontStyle);
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSUAttributeTag tag = kATSUFontTag;
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ByteCount size = sizeof(ATSUFontID);
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSUFontID *valueArray[1] = {&fontId};
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    OSStatus status = ATSUSetAttributes(fontStyle, 1, &tag, &size, (void* const*)valueArray);
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (status != noErr) {
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ATSUDisposeStyle(fontStyle);
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (wkGetATSStyleGroup(fontStyle, &fontData->m_styleGroup) != noErr) {
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ATSUDisposeStyle(fontStyle);
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSUDisposeStyle(fontStyle);
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic NSString *webFallbackFontFamily(void)
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(RetainPtr<NSString>, webFallbackFontFamily, ([[NSFont systemFontOfSize:16.0f] familyName]));
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return webFallbackFontFamily.get();
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !ERROR_DISABLED
1045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#if defined(__LP64__) || (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic NSString* pathFromFont(NSFont*)
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // FMGetATSFontRefFromFont is not available. As pathFromFont is only used for debugging purposes,
1085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // returning nil is acceptable.
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nil;
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic NSString* pathFromFont(NSFont *font)
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef BUILDING_ON_TIGER
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSFontRef atsFont = FMGetATSFontRefFromFont(CTFontGetPlatformFont(toCTFontRef(font), 0));
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ATSFontRef atsFont = FMGetATSFontRefFromFont(wkGetNSFontATSUFontId(font));
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FSRef fileRef;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef BUILDING_ON_TIGER
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    OSStatus status = ATSFontGetFileReference(atsFont, &fileRef);
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (status != noErr)
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FSSpec oFile;
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    OSStatus status = ATSFontGetFileSpecification(atsFont, &oFile);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (status != noErr)
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    status = FSpMakeFSRef(&oFile, &fileRef);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (status != noErr)
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UInt8 filePathBuffer[PATH_MAX];
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    status = FSRefMakePath(&fileRef, filePathBuffer, PATH_MAX);
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (status == noErr)
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return [NSString stringWithUTF8String:(const char*)filePathBuffer];
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nil;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // __LP64__
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // !ERROR_DISABLED
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimpleFontData::platformInit()
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_styleGroup = 0;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ATSUI)
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_ATSUMirrors = false;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_checkedShapesArabic = false;
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_shapesArabic = false;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool failedSetup = false;
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!initFontData(this)) {
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Ack! Something very bad happened, like a corrupt font.
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Try looking for an alternate 'base' font for this renderer.
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Special case hack to use "Times New Roman" in place of "Times".
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // "Times RO" is a common font whose family name is "Times".
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // It overrides the normal "Times" family font.
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // It also appears to have a corrupt regular variant.
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSString *fallbackFontFamily;
1695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ([[m_platformData.font() familyName] isEqual:@"Times"])
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fallbackFontFamily = @"Times New Roman";
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fallbackFontFamily = webFallbackFontFamily();
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Try setting up the alternate font.
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This is a last ditch effort to use a substitute font when something has gone wrong.
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !ERROR_DISABLED
1775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RetainPtr<NSFont> initialFont = m_platformData.font();
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_platformData.font())
1805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:fallbackFontFamily]);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
1825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_platformData.setFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !ERROR_DISABLED
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSString *filePath = pathFromFont(initialFont.get());
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!filePath)
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            filePath = @"not known";
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!initFontData(this)) {
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // OK, couldn't setup Times New Roman as an alternate to Times, fallback
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // on the system font.  If this fails we have no alternative left.
1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:webFallbackFontFamily()]);
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!initFontData(this)) {
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    failedSetup = true;
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We tried the requested font and the system font. No joy. We have to give up.
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                failedSetup = true;
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Report the problem.
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("Corrupt font detected, using %@ in place of %@ located at \"%@\".",
2075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            [m_platformData.font() familyName], [initialFont.get() familyName], filePath);
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If all else fails, try to set up using the system font.
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This is probably because Times and Times New Roman are both unavailable.
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (failedSetup) {
2135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_platformData.setFont([NSFont systemFontOfSize:[m_platformData.font() pointSize]]);
2145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        initFontData(this);
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int iAscent;
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int iDescent;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int iLineGap;
2212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned unitsPerEm;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
2232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkGetFontMetrics(m_platformData.cgFont(), &iAscent, &iDescent, &iLineGap, &unitsPerEm);
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    iAscent = CGFontGetAscent(m_platformData.cgFont());
2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    iDescent = CGFontGetDescent(m_platformData.cgFont());
2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    iLineGap = CGFontGetLeading(m_platformData.cgFont());
2282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    float pointSize = m_platformData.m_size;
2322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float ascent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
2332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float descent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
2342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float lineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We need to adjust Times, Helvetica, and Courier to closely match the
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // vertical metrics of their Microsoft counterparts that are the de facto
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // web standard. The AppKit adjustment of 20% is too big and is
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // incorrectly added to line spacing, so we use a 15% adjustment instead
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and add it to the ascent.
2415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSString *familyName = [m_platformData.font() familyName];
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
2432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
2442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if defined(BUILDING_ON_LEOPARD)
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if ([familyName isEqualToString:@"Geeza Pro"]) {
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Geeza Pro has glyphs that draw slightly above the ascent or far below the descent. Adjust
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // those vertical metrics to better match reality, so that diacritics at the bottom of one line
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // do not overlap diacritics at the top of the next line.
2492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ascent *= 1.08f;
2502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        descent *= 2.f;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Compute and store line spacing, before the line metrics hacks are applied.
2552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
2562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Hack Hiragino line metrics to allow room for marked text underlines.
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // <rdar://problem/5386183>
2592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (descent < 3 && lineGap >= 3 && [familyName hasPrefix:@"Hiragino"]) {
2602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        lineGap -= 3 - descent;
2612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        descent = 3;
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
2656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // The check doesn't look neat but this is what AppKit does for vertical writing...
2666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        RetainPtr<CFArrayRef> tableTags(AdoptCF, CTFontCopyAvailableTables(m_platformData.ctFont(), kCTFontTableOptionExcludeSynthetic));
2676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CFIndex numTables = CFArrayGetCount(tableTags.get());
2686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        for (CFIndex index = 0; index < numTables; ++index) {
2696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index);
2706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            if (tag == kCTFontTableVhea || tag == kCTFontTableVORG) {
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block                m_hasVerticalGlyphs = true;
2726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                break;
2736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            }
2746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        }
2756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float xHeight;
2782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2792bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (platformData().orientation() == Horizontal) {
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the
2812bde8e466a4451c7319e3a072d118917957d6554Steve Block        // reported x-height to only include the portion of the glyph that is above the baseline.
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block        GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
2832bde8e466a4451c7319e3a072d118917957d6554Steve Block        NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (xGlyph)
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block            xHeight = -CGRectGetMinY(platformBoundsForGlyph(xGlyph));
2862bde8e466a4451c7319e3a072d118917957d6554Steve Block        else
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block            xHeight = scaleEmToUnits(CGFontGetXHeight(m_platformData.cgFont()), unitsPerEm) * pointSize;
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block        xHeight = verticalRightOrientationFontData()->fontMetrics().xHeight();
2902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setUnitsPerEm(unitsPerEm);
2922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setAscent(ascent);
2932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setDescent(descent);
2942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setLineGap(lineGap);
2952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setXHeight(xHeight);
2965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
2972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
298ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockstatic CFDataRef copyFontTableForTag(FontPlatformData& platformData, FourCharCode tableName)
299692e5dbf12901edacf14812a6fae25462920af42Steve Block{
300692e5dbf12901edacf14812a6fae25462920af42Steve Block#ifdef BUILDING_ON_TIGER
301692e5dbf12901edacf14812a6fae25462920af42Steve Block    ATSFontRef atsFont = FMGetATSFontRefFromFont(platformData.m_atsuFontID);
302692e5dbf12901edacf14812a6fae25462920af42Steve Block
303692e5dbf12901edacf14812a6fae25462920af42Steve Block    ByteCount tableSize;
304692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (ATSFontGetTable(atsFont, tableName, 0, 0, NULL, &tableSize) != noErr)
305692e5dbf12901edacf14812a6fae25462920af42Steve Block        return 0;
306692e5dbf12901edacf14812a6fae25462920af42Steve Block
307692e5dbf12901edacf14812a6fae25462920af42Steve Block    CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, tableSize);
308692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (!data)
309692e5dbf12901edacf14812a6fae25462920af42Steve Block        return 0;
310692e5dbf12901edacf14812a6fae25462920af42Steve Block
311692e5dbf12901edacf14812a6fae25462920af42Steve Block    CFDataIncreaseLength(data, tableSize);
312692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (ATSFontGetTable(atsFont, tableName, 0, tableSize, CFDataGetMutableBytePtr(data), &tableSize) != noErr) {
313692e5dbf12901edacf14812a6fae25462920af42Steve Block        CFRelease(data);
314692e5dbf12901edacf14812a6fae25462920af42Steve Block        return 0;
315692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
316692e5dbf12901edacf14812a6fae25462920af42Steve Block
317692e5dbf12901edacf14812a6fae25462920af42Steve Block    return data;
318692e5dbf12901edacf14812a6fae25462920af42Steve Block#else
319692e5dbf12901edacf14812a6fae25462920af42Steve Block    return CGFontCopyTableForTag(platformData.cgFont(), tableName);
320692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
321692e5dbf12901edacf14812a6fae25462920af42Steve Block}
3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid SimpleFontData::platformCharWidthInit()
3245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
325692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_avgCharWidth = 0;
326692e5dbf12901edacf14812a6fae25462920af42Steve Block    m_maxCharWidth = 0;
327692e5dbf12901edacf14812a6fae25462920af42Steve Block
328692e5dbf12901edacf14812a6fae25462920af42Steve Block    RetainPtr<CFDataRef> os2Table(AdoptCF, copyFontTableForTag(m_platformData, 'OS/2'));
329692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (os2Table && CFDataGetLength(os2Table.get()) >= 4) {
330692e5dbf12901edacf14812a6fae25462920af42Steve Block        const UInt8* os2 = CFDataGetBytePtr(os2Table.get());
331692e5dbf12901edacf14812a6fae25462920af42Steve Block        SInt16 os2AvgCharWidth = os2[2] * 256 + os2[3];
3322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_avgCharWidth = scaleEmToUnits(os2AvgCharWidth, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
3335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
335692e5dbf12901edacf14812a6fae25462920af42Steve Block    RetainPtr<CFDataRef> headTable(AdoptCF, copyFontTableForTag(m_platformData, 'head'));
336692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (headTable && CFDataGetLength(headTable.get()) >= 42) {
337692e5dbf12901edacf14812a6fae25462920af42Steve Block        const UInt8* head = CFDataGetBytePtr(headTable.get());
338692e5dbf12901edacf14812a6fae25462920af42Steve Block        ushort uxMin = head[36] * 256 + head[37];
339692e5dbf12901edacf14812a6fae25462920af42Steve Block        ushort uxMax = head[40] * 256 + head[41];
340692e5dbf12901edacf14812a6fae25462920af42Steve Block        SInt16 xMin = static_cast<SInt16>(uxMin);
341692e5dbf12901edacf14812a6fae25462920af42Steve Block        SInt16 xMax = static_cast<SInt16>(uxMax);
342692e5dbf12901edacf14812a6fae25462920af42Steve Block        float diff = static_cast<float>(xMax - xMin);
3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_maxCharWidth = scaleEmToUnits(diff, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
344692e5dbf12901edacf14812a6fae25462920af42Steve Block    }
3455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
3475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    initCharWidths();
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimpleFontData::platformDestroy()
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
352f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!isCustomFont() && m_derivedFontData) {
353f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        // These come from the cache.
354f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_derivedFontData->smallCaps)
355f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            fontCache()->releaseFontData(m_derivedFontData->smallCaps.leakPtr());
356f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
357f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_derivedFontData->emphasisMark)
358f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            fontCache()->releaseFontData(m_derivedFontData->emphasisMark.leakPtr());
3596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
3606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_styleGroup)
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        wkReleaseStyleGroup(m_styleGroup);
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if USE(ATSUI)
366d0825bca7fe65beaee391d30da42e937db621564Steve Block    HashMap<unsigned, ATSUStyle>::iterator end = m_ATSUStyleMap.end();
367d0825bca7fe65beaee391d30da42e937db621564Steve Block    for (HashMap<unsigned, ATSUStyle>::iterator it = m_ATSUStyleMap.begin(); it != end; ++it)
368d0825bca7fe65beaee391d30da42e937db621564Steve Block        ATSUDisposeStyle(it->second);
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
372f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochSimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
374f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (isCustomFont()) {
375f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        FontPlatformData scaledFontData(m_platformData);
376f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        scaledFontData.m_size = scaledFontData.m_size * scaleFactor;
377f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return new SimpleFontData(scaledFontData, true, false);
378f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
379f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    BEGIN_BLOCK_OBJC_EXCEPTIONS;
381f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    float size = m_platformData.size() * scaleFactor;
3822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, false, false, m_platformData.orientation());
383f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
384f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // AppKit resets the type information (screen/printer) when you convert a font to a different size.
385f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // We have to fix up the font that we're handed back.
386f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    scaledFontData.setFont(fontDescription.usePrinterFont() ? [scaledFontData.font() printerFont] : [scaledFontData.font() screenFont]);
387f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
388f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (scaledFontData.font()) {
389f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        NSFontManager *fontManager = [NSFontManager sharedFontManager];
390f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.font()];
391f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
392f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_platformData.m_syntheticBold)
393f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            fontTraits |= NSBoldFontMask;
394f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_platformData.m_syntheticOblique)
395f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            fontTraits |= NSItalicFontMask;
396f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
397f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        NSFontTraitMask scaledFontTraits = [fontManager traitsOfFont:scaledFontData.font()];
398f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        scaledFontData.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(scaledFontTraits & NSBoldFontMask);
399f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask);
400f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
401f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return fontCache()->getCachedFontData(&scaledFontData);
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
403f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    END_BLOCK_OBJC_EXCEPTIONS;
404f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return 0;
406f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
407f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
408f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochSimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
409f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
410f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData)
411f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData = DerivedFontData::create(isCustomFont());
412f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData->smallCaps)
413f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData->smallCaps = scaledFontData(fontDescription, smallCapsFontSizeMultiplier);
414f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
415f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_derivedFontData->smallCaps.get();
416f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
417f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
418f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochSimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
419f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
420f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData)
421f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData = DerivedFontData::create(isCustomFont());
422f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData->emphasisMark)
423f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5f);
424f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
425f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_derivedFontData->emphasisMark.get();
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimpleFontData::containsCharacters(const UChar* characters, int length) const
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO];
4315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSCharacterSet *set = [[m_platformData.font() coveredCharacterSet] invertedSet];
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [string release];
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimpleFontData::determinePitch()
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSFont* f = m_platformData.font();
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Special case Osaka-Mono.
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // According to <rdar://problem/3999467>, we should treat Osaka-Mono as fixed pitch.
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Note that the AppKit does not report Osaka-Mono as fixed pitch.
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Special case MS-PGothic.
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // According to <rdar://problem/4032938>, we should not treat MS-PGothic as fixed pitch.
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Note that AppKit does report MS-PGothic as fixed pitch.
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Special case MonotypeCorsiva
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // According to <rdar://problem/5454704>, we should not treat MonotypeCorsiva as fixed pitch.
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Note that AppKit does report MonotypeCorsiva as fixed pitch.
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *name = [f fontName];
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_treatAsFixedPitch = ([f isFixedPitch] || [f _isFakeFixedPitch] ||
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           [name caseInsensitiveCompare:@"Osaka-Mono"] == NSOrderedSame) &&
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           [name caseInsensitiveCompare:@"MS-PGothic"] != NSOrderedSame &&
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame;
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
45921939df44de1705786c545cd1bf519d47250322dBen MurdochFloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
46021939df44de1705786c545cd1bf519d47250322dBen Murdoch{
46121939df44de1705786c545cd1bf519d47250322dBen Murdoch    FloatRect boundingBox;
4622bde8e466a4451c7319e3a072d118917957d6554Steve Block    boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
4632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    boundingBox.setY(-boundingBox.maxY());
4645af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (m_syntheticBoldOffset)
4655af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
4665af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
46721939df44de1705786c545cd1bf519d47250322dBen Murdoch    return boundingBox;
46821939df44de1705786c545cd1bf519d47250322dBen Murdoch}
46921939df44de1705786c545cd1bf519d47250322dBen Murdoch
47021939df44de1705786c545cd1bf519d47250322dBen Murdochfloat SimpleFontData::platformWidthForGlyph(Glyph glyph) const
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CGSize advance;
4732bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (platformData().orientation() == Horizontal || m_isBrokenIdeographFallback) {
474e14391e94c850b8bd03680c23b38978db68687a8John Reck        NSFont* font = platformData().font();
475e14391e94c850b8bd03680c23b38978db68687a8John Reck        float pointSize = platformData().m_size;
476e14391e94c850b8bd03680c23b38978db68687a8John Reck        CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
477e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (!wkGetGlyphTransformedAdvances(platformData().cgFont(), font, &m, &glyph, &advance)) {
478e14391e94c850b8bd03680c23b38978db68687a8John Reck            LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
479e14391e94c850b8bd03680c23b38978db68687a8John Reck            advance.width = 0;
480e14391e94c850b8bd03680c23b38978db68687a8John Reck        }
481e14391e94c850b8bd03680c23b38978db68687a8John Reck    } else
482e14391e94c850b8bd03680c23b38978db68687a8John Reck        CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), kCTFontVerticalOrientation, &glyph, &advance, 1);
483e14391e94c850b8bd03680c23b38978db68687a8John Reck
48421939df44de1705786c545cd1bf519d47250322dBen Murdoch    return advance.width + m_syntheticBoldOffset;
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
488