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