6a1770723df3ecd47354b8a5ad6710f0431790cf
[WebKit-https.git] / Source / WebCore / platform / graphics / cocoa / FontPlatformDataCocoa.mm
1 /*
2  * This file is part of the internal font implementation.
3  *
4  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
5  * Copyright (c) 2010 Google Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #import "config.h"
25 #import "FontPlatformData.h"
26
27 #import "PlatformString.h"
28 #import "WebCoreSystemInterface.h"
29 #import <AppKit/NSFont.h>
30
31 namespace WebCore {
32
33 // These CoreText Text Spacing feature selectors are not defined in CoreText.
34 enum TextSpacingCTFeatureSelector { TextSpacingProportional, TextSpacingFullWidth, TextSpacingHalfWidth, TextSpacingThirdWidth, TextSpacingQuarterWidth };
35
36 #if PLATFORM(MAC)
37 void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFontRef& cgFont)
38 {
39     outNSFont = nsFont;
40 #ifndef BUILDING_ON_TIGER
41     cgFont = CTFontCopyGraphicsFont(toCTFontRef(nsFont), 0);
42 #else
43     cgFont = wkGetCGFontFromNSFont(nsFont);
44 #endif
45 }
46 #endif  // PLATFORM(MAC)
47
48 FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
49                                    TextOrientation textOrientation, FontWidthVariant widthVariant)
50     : m_syntheticBold(syntheticBold)
51     , m_syntheticOblique(syntheticOblique)
52     , m_orientation(orientation)
53     , m_textOrientation(textOrientation)
54     , m_size(size)
55     , m_widthVariant(widthVariant)
56     , m_font(nsFont)
57 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
58     // FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might
59     // have blocked font loading, in which case we'll only have the real loaded font file after the call to loadFont().
60     , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait)
61 #else
62     , m_isColorBitmapFont(false)
63 #endif
64 {
65     ASSERT_ARG(nsFont, nsFont);
66
67     CGFontRef cgFont = 0;
68     loadFont(nsFont, size, m_font, cgFont);
69
70     if (m_font)
71         CFRetain(m_font);
72
73 #ifndef BUILDING_ON_TIGER
74     m_cgFont.adoptCF(cgFont);
75 #else
76     m_cgFont = cgFont;
77 #endif
78 }
79
80 FontPlatformData:: ~FontPlatformData()
81 {
82     if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
83         CFRelease(m_font);
84 }
85
86 void FontPlatformData::platformDataInit(const FontPlatformData& f)
87 {
88     m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font;
89
90     m_cgFont = f.m_cgFont;
91     m_CTFont = f.m_CTFont;
92
93 #if PLATFORM(CHROMIUM) && OS(DARWIN)
94     m_inMemoryFont = f.m_inMemoryFont;
95 #endif
96 }
97
98 const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformData& f)
99 {
100     m_cgFont = f.m_cgFont;
101     if (m_font == f.m_font)
102         return *this;
103     if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1))
104         CFRetain(f.m_font);
105     if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
106         CFRelease(m_font);
107     m_font = f.m_font;
108     m_CTFont = f.m_CTFont;
109 #if PLATFORM(CHROMIUM) && OS(DARWIN)
110     m_inMemoryFont = f.m_inMemoryFont;
111 #endif
112     return *this;
113 }
114
115 bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const
116 {
117     return m_font == other.m_font
118         && m_cgFont == other.m_cgFont;
119 }
120
121 void FontPlatformData::setFont(NSFont *font)
122 {
123     ASSERT_ARG(font, font);
124     ASSERT(m_font != reinterpret_cast<NSFont *>(-1));
125
126     if (m_font == font)
127         return;
128
129     CFRetain(font);
130     if (m_font)
131         CFRelease(m_font);
132     m_font = font;
133     m_size = [font pointSize];
134     
135     CGFontRef cgFont = 0;
136     NSFont* loadedFont = 0;
137     loadFont(m_font, m_size, loadedFont, cgFont);
138     
139 #if PLATFORM(CHROMIUM) && OS(DARWIN)
140     // If loadFont replaced m_font with a fallback font, then release the
141     // previous font to counter the retain above. Then retain the new font.
142     if (loadedFont != m_font) {
143         CFRelease(m_font);
144         CFRetain(loadedFont);
145         m_font = loadedFont;
146     }
147 #endif
148     
149 #ifndef BUILDING_ON_TIGER
150     m_cgFont.adoptCF(cgFont);
151 #else
152     m_cgFont = cgFont;
153 #endif
154 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
155     m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait;
156 #endif
157     m_CTFont = 0;
158 }
159
160 bool FontPlatformData::roundsGlyphAdvances() const
161 {
162     return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
163 }
164
165 bool FontPlatformData::allowsLigatures() const
166 {
167     return ![[m_font coveredCharacterSet] characterIsMember:'a'];
168 }
169
170 inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant)
171 {
172     switch(variant) {
173     case RegularWidth:
174         return TextSpacingProportional;
175
176     case HalfWidth:
177         return TextSpacingHalfWidth;
178
179     case ThirdWidth:
180         return TextSpacingThirdWidth;
181
182     case QuarterWidth:
183         return TextSpacingQuarterWidth;
184     }
185
186     ASSERT_NOT_REACHED();
187     return TextSpacingProportional;
188 }
189
190 CTFontRef FontPlatformData::ctFont() const
191 {
192     if (m_widthVariant == RegularWidth) {
193         if (m_font)
194             return toCTFontRef(m_font);
195         if (!m_CTFont)
196             m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
197         return m_CTFont.get();
198     }
199     
200     if (!m_CTFont) {
201         int featureTypeValue = kTextSpacingType;
202         int featureSelectorValue = mapFontWidthVariantToCTFeatureSelector(m_widthVariant);
203         RetainPtr<CTFontRef> sourceFont(AdoptCF, CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
204         RetainPtr<CTFontDescriptorRef> sourceDescriptor(AdoptCF, CTFontCopyFontDescriptor(sourceFont.get()));
205         RetainPtr<CFNumberRef> featureType(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureTypeValue));
206         RetainPtr<CFNumberRef> featureSelector(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorValue));
207         RetainPtr<CTFontDescriptorRef> newDescriptor(AdoptCF, CTFontDescriptorCreateCopyWithFeature(sourceDescriptor.get(), featureType.get(), featureSelector.get()));
208         RetainPtr<CTFontRef> newFont(AdoptCF, CTFontCreateWithFontDescriptor(newDescriptor.get(), m_size, 0));
209
210         m_CTFont = newFont.get() ? newFont : sourceFont;
211     }
212     return m_CTFont.get();
213 }
214
215 #ifndef NDEBUG
216 String FontPlatformData::description() const
217 {
218     RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont()));
219     return String(cgFontDescription.get()) + " " + String::number(m_size)
220             + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : "") + (m_orientation ? " vertical orientation" : "");
221 }
222 #endif
223
224 } // namespace WebCore