OLD | NEW |
| (Empty) |
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 "core/platform/graphics/FontPlatformData.h" | |
26 | |
27 #import <AppKit/NSFont.h> | |
28 #import <AvailabilityMacros.h> | |
29 #import <wtf/text/WTFString.h> | |
30 | |
31 #if OS(MACOSX) | |
32 #import "core/platform/graphics/harfbuzz/HarfBuzzFace.h" | |
33 #endif | |
34 | |
35 namespace WebCore { | |
36 | |
37 // These CoreText Text Spacing feature selectors are not defined in CoreText. | |
38 enum TextSpacingCTFeatureSelector { TextSpacingProportional, TextSpacingFullWidt
h, TextSpacingHalfWidth, TextSpacingThirdWidth, TextSpacingQuarterWidth }; | |
39 | |
40 FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool isPrinterFon
t, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontW
idthVariant widthVariant) | |
41 : m_syntheticBold(syntheticBold) | |
42 , m_syntheticOblique(syntheticOblique) | |
43 , m_orientation(orientation) | |
44 , m_size(size) | |
45 , m_widthVariant(widthVariant) | |
46 , m_font(nsFont) | |
47 , m_isColorBitmapFont(false) | |
48 , m_isCompositeFontReference(false) | |
49 , m_isPrinterFont(isPrinterFont) | |
50 { | |
51 ASSERT_ARG(nsFont, nsFont); | |
52 | |
53 CGFontRef cgFont = 0; | |
54 loadFont(nsFont, size, m_font, cgFont); | |
55 | |
56 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 | |
57 // FIXME: Chromium: The following code isn't correct for the Chromium port s
ince the sandbox might | |
58 // have blocked font loading, in which case we'll only have the real loaded
font file after the call to loadFont(). | |
59 { | |
60 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(m_font
)); | |
61 m_isColorBitmapFont = traits & kCTFontColorGlyphsTrait; | |
62 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 | |
63 m_isCompositeFontReference = traits & kCTFontCompositeTrait; | |
64 #endif | |
65 } | |
66 #endif | |
67 | |
68 if (m_font) | |
69 CFRetain(m_font); | |
70 | |
71 m_cgFont.adoptCF(cgFont); | |
72 } | |
73 | |
74 FontPlatformData:: ~FontPlatformData() | |
75 { | |
76 if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) | |
77 CFRelease(m_font); | |
78 } | |
79 | |
80 void FontPlatformData::platformDataInit(const FontPlatformData& f) | |
81 { | |
82 m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? [f.m_font
retain] : f.m_font; | |
83 | |
84 m_cgFont = f.m_cgFont; | |
85 m_CTFont = f.m_CTFont; | |
86 | |
87 #if OS(MACOSX) | |
88 m_inMemoryFont = f.m_inMemoryFont; | |
89 m_harfBuzzFace = f.m_harfBuzzFace; | |
90 #endif | |
91 } | |
92 | |
93 const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformD
ata& f) | |
94 { | |
95 m_cgFont = f.m_cgFont; | |
96 if (m_font == f.m_font) | |
97 return *this; | |
98 if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1)) | |
99 CFRetain(f.m_font); | |
100 if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) | |
101 CFRelease(m_font); | |
102 m_font = f.m_font; | |
103 m_CTFont = f.m_CTFont; | |
104 #if OS(MACOSX) | |
105 m_inMemoryFont = f.m_inMemoryFont; | |
106 m_harfBuzzFace = f.m_harfBuzzFace; | |
107 #endif | |
108 return *this; | |
109 } | |
110 | |
111 bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const | |
112 { | |
113 if (m_font || other.m_font) | |
114 return m_font == other.m_font; | |
115 return m_cgFont == other.m_cgFont; | |
116 } | |
117 | |
118 void FontPlatformData::setFont(NSFont *font) | |
119 { | |
120 ASSERT_ARG(font, font); | |
121 ASSERT(m_font != reinterpret_cast<NSFont *>(-1)); | |
122 | |
123 if (m_font == font) | |
124 return; | |
125 | |
126 CFRetain(font); | |
127 if (m_font) | |
128 CFRelease(m_font); | |
129 m_font = font; | |
130 m_size = [font pointSize]; | |
131 | |
132 CGFontRef cgFont = 0; | |
133 NSFont* loadedFont = 0; | |
134 loadFont(m_font, m_size, loadedFont, cgFont); | |
135 | |
136 #if OS(MACOSX) | |
137 // If loadFont replaced m_font with a fallback font, then release the | |
138 // previous font to counter the retain above. Then retain the new font. | |
139 if (loadedFont != m_font) { | |
140 CFRelease(m_font); | |
141 CFRetain(loadedFont); | |
142 m_font = loadedFont; | |
143 } | |
144 #endif | |
145 | |
146 m_cgFont.adoptCF(cgFont); | |
147 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 | |
148 { | |
149 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(m_font
)); | |
150 m_isColorBitmapFont = traits & kCTFontColorGlyphsTrait; | |
151 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 | |
152 m_isCompositeFontReference = traits & kCTFontCompositeTrait; | |
153 #endif | |
154 } | |
155 #endif | |
156 m_CTFont = 0; | |
157 } | |
158 | |
159 bool FontPlatformData::roundsGlyphAdvances() const | |
160 { | |
161 return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderi
ngMode; | |
162 } | |
163 | |
164 bool FontPlatformData::allowsLigatures() const | |
165 { | |
166 return ![[m_font coveredCharacterSet] characterIsMember:'a']; | |
167 } | |
168 | |
169 inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant) | |
170 { | |
171 switch(variant) { | |
172 case RegularWidth: | |
173 return TextSpacingProportional; | |
174 | |
175 case HalfWidth: | |
176 return TextSpacingHalfWidth; | |
177 | |
178 case ThirdWidth: | |
179 return TextSpacingThirdWidth; | |
180 | |
181 case QuarterWidth: | |
182 return TextSpacingQuarterWidth; | |
183 } | |
184 | |
185 ASSERT_NOT_REACHED(); | |
186 return TextSpacingProportional; | |
187 } | |
188 | |
189 static CFDictionaryRef createFeatureSettingDictionary(int featureTypeIdentifier,
int featureSelectorIdentifier) | |
190 { | |
191 RetainPtr<CFNumberRef> featureTypeIdentifierNumber(AdoptCF, CFNumberCreate(k
CFAllocatorDefault, kCFNumberIntType, &featureTypeIdentifier)); | |
192 RetainPtr<CFNumberRef> featureSelectorIdentifierNumber(AdoptCF, CFNumberCrea
te(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorIdentifier)); | |
193 | |
194 const void* settingKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatur
eSelectorIdentifierKey }; | |
195 const void* settingValues[] = { featureTypeIdentifierNumber.get(), featureSe
lectorIdentifierNumber.get() }; | |
196 | |
197 return CFDictionaryCreate(kCFAllocatorDefault, settingKeys, settingValues, W
TF_ARRAY_LENGTH(settingKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionary
ValueCallBacks); | |
198 } | |
199 | |
200 static CTFontDescriptorRef cascadeToLastResortFontDescriptor() | |
201 { | |
202 static CTFontDescriptorRef descriptor; | |
203 if (descriptor) | |
204 return descriptor; | |
205 | |
206 const void* keys[] = { kCTFontCascadeListAttribute }; | |
207 const void* descriptors[] = { CTFontDescriptorCreateWithNameAndSize(CFSTR("L
astResort"), 0) }; | |
208 const void* values[] = { CFArrayCreate(kCFAllocatorDefault, descriptors, WTF
_ARRAY_LENGTH(descriptors), &kCFTypeArrayCallBacks) }; | |
209 RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocat
orDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks)); | |
210 | |
211 descriptor = CTFontDescriptorCreateWithAttributes(attributes.get()); | |
212 | |
213 return descriptor; | |
214 } | |
215 | |
216 static CTFontDescriptorRef cascadeToLastResortAndDisableSwashesFontDescriptor() | |
217 { | |
218 static CTFontDescriptorRef descriptor; | |
219 if (descriptor) | |
220 return descriptor; | |
221 | |
222 RetainPtr<CFDictionaryRef> lineInitialSwashesOffSetting(AdoptCF, createFeatu
reSettingDictionary(kSmartSwashType, kLineInitialSwashesOffSelector)); | |
223 RetainPtr<CFDictionaryRef> lineFinalSwashesOffSetting(AdoptCF, createFeature
SettingDictionary(kSmartSwashType, kLineFinalSwashesOffSelector)); | |
224 | |
225 const void* settingDictionaries[] = { lineInitialSwashesOffSetting.get(), li
neFinalSwashesOffSetting.get() }; | |
226 RetainPtr<CFArrayRef> featureSettings(AdoptCF, CFArrayCreate(kCFAllocatorDef
ault, settingDictionaries, WTF_ARRAY_LENGTH(settingDictionaries), &kCFTypeArrayC
allBacks)); | |
227 | |
228 const void* keys[] = { kCTFontFeatureSettingsAttribute }; | |
229 const void* values[] = { featureSettings.get() }; | |
230 RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocat
orDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks)); | |
231 | |
232 descriptor = CTFontDescriptorCreateCopyWithAttributes(cascadeToLastResortFon
tDescriptor(), attributes.get()); | |
233 | |
234 return descriptor; | |
235 } | |
236 | |
237 String FontPlatformData::fontFamilyName() const | |
238 { | |
239 return String(CTFontCopyDisplayName(ctFont())); | |
240 } | |
241 | |
242 CTFontRef FontPlatformData::ctFont() const | |
243 { | |
244 if (m_CTFont) | |
245 return m_CTFont.get(); | |
246 | |
247 if (m_inMemoryFont) { | |
248 m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_inMemoryFont->cgFont(),
m_size, 0, cascadeToLastResortFontDescriptor())); | |
249 return m_CTFont.get(); | |
250 } | |
251 | |
252 m_CTFont = toCTFontRef(m_font); | |
253 if (m_CTFont) { | |
254 CTFontDescriptorRef fontDescriptor; | |
255 RetainPtr<CFStringRef> postScriptName(AdoptCF, CTFontCopyPostScriptName(
m_CTFont.get())); | |
256 // Hoefler Text Italic has line-initial and -final swashes enabled by de
fault, so disable them. | |
257 if (CFEqual(postScriptName.get(), CFSTR("HoeflerText-Italic")) || CFEqua
l(postScriptName.get(), CFSTR("HoeflerText-BlackItalic"))) | |
258 fontDescriptor = cascadeToLastResortAndDisableSwashesFontDescriptor(
); | |
259 else | |
260 fontDescriptor = cascadeToLastResortFontDescriptor(); | |
261 m_CTFont.adoptCF(CTFontCreateCopyWithAttributes(m_CTFont.get(), m_size,
0, fontDescriptor)); | |
262 } else | |
263 m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0,
cascadeToLastResortFontDescriptor())); | |
264 | |
265 if (m_widthVariant != RegularWidth) { | |
266 int featureTypeValue = kTextSpacingType; | |
267 int featureSelectorValue = mapFontWidthVariantToCTFeatureSelector(m_widt
hVariant); | |
268 RetainPtr<CTFontDescriptorRef> sourceDescriptor(AdoptCF, CTFontCopyFontD
escriptor(m_CTFont.get())); | |
269 RetainPtr<CFNumberRef> featureType(AdoptCF, CFNumberCreate(kCFAllocatorD
efault, kCFNumberIntType, &featureTypeValue)); | |
270 RetainPtr<CFNumberRef> featureSelector(AdoptCF, CFNumberCreate(kCFAlloca
torDefault, kCFNumberIntType, &featureSelectorValue)); | |
271 RetainPtr<CTFontDescriptorRef> newDescriptor(AdoptCF, CTFontDescriptorCr
eateCopyWithFeature(sourceDescriptor.get(), featureType.get(), featureSelector.g
et())); | |
272 RetainPtr<CTFontRef> newFont(AdoptCF, CTFontCreateWithFontDescriptor(new
Descriptor.get(), m_size, 0)); | |
273 | |
274 if (newFont) | |
275 m_CTFont = newFont; | |
276 } | |
277 | |
278 return m_CTFont.get(); | |
279 } | |
280 | |
281 #if OS(MACOSX) | |
282 static bool isAATFont(CTFontRef ctFont) | |
283 { | |
284 CFDataRef table = CTFontCopyTable(ctFont, kCTFontTableMort, 0); | |
285 if (table) { | |
286 CFRelease(table); | |
287 return true; | |
288 } | |
289 table = CTFontCopyTable(ctFont, kCTFontTableMorx, 0); | |
290 if (table) { | |
291 CFRelease(table); | |
292 return true; | |
293 } | |
294 return false; | |
295 } | |
296 | |
297 HarfBuzzFace* FontPlatformData::harfBuzzFace() | |
298 { | |
299 CTFontRef font = ctFont(); | |
300 // HarfBuzz can't handle AAT font | |
301 if (isAATFont(font)) | |
302 return 0; | |
303 | |
304 if (!m_harfBuzzFace) { | |
305 uint64_t uniqueID = reinterpret_cast<uintptr_t>(font); | |
306 m_harfBuzzFace = HarfBuzzFace::create(const_cast<FontPlatformData*>(this
), uniqueID); | |
307 } | |
308 return m_harfBuzzFace.get(); | |
309 } | |
310 #endif | |
311 | |
312 #ifndef NDEBUG | |
313 String FontPlatformData::description() const | |
314 { | |
315 RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont()
)); | |
316 return String(cgFontDescription.get()) + " " + String::number(m_size) | |
317 + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ?
" synthetic oblique" : "") + (m_orientation ? " vertical orientation" : ""); | |
318 } | |
319 #endif | |
320 | |
321 } // namespace WebCore | |
OLD | NEW |