https://bugs.webkit.org/show_bug.cgi?id=48540, support the text-orientation CSS property.
[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(const FontPlatformData& f)
81 {
82     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;
83
84     m_syntheticBold = f.m_syntheticBold;
85     m_syntheticOblique = f.m_syntheticOblique;
86     m_size = f.m_size;
87     m_widthVariant = f.m_widthVariant;
88     m_cgFont = f.m_cgFont;
89     m_isColorBitmapFont = f.m_isColorBitmapFont;
90     m_orientation = f.m_orientation;
91     m_textOrientation = f.m_textOrientation;
92     m_CTFont = f.m_CTFont;
93 #if PLATFORM(CHROMIUM) && OS(DARWIN)
94     m_inMemoryFont = f.m_inMemoryFont;
95 #endif
96 }
97
98 FontPlatformData:: ~FontPlatformData()
99 {
100     if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
101         CFRelease(m_font);
102 }
103
104 const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
105 {
106     m_syntheticBold = f.m_syntheticBold;
107     m_syntheticOblique = f.m_syntheticOblique;
108     m_size = f.m_size;
109     m_widthVariant = f.m_widthVariant;
110     m_cgFont = f.m_cgFont;
111     if (m_font == f.m_font)
112         return *this;
113     if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1))
114         CFRetain(f.m_font);
115     if (m_font && m_font != reinterpret_cast<NSFont *>(-1))
116         CFRelease(m_font);
117     m_font = f.m_font;
118     m_isColorBitmapFont = f.m_isColorBitmapFont;
119     m_orientation = f.m_orientation;
120     m_textOrientation = f.m_textOrientation;
121     m_CTFont = f.m_CTFont;
122 #if PLATFORM(CHROMIUM) && OS(DARWIN)
123     m_inMemoryFont = f.m_inMemoryFont;
124 #endif
125     return *this;
126 }
127
128 void FontPlatformData::setFont(NSFont *font)
129 {
130     ASSERT_ARG(font, font);
131     ASSERT(m_font != reinterpret_cast<NSFont *>(-1));
132
133     if (m_font == font)
134         return;
135
136     CFRetain(font);
137     if (m_font)
138         CFRelease(m_font);
139     m_font = font;
140     m_size = [font pointSize];
141     
142     CGFontRef cgFont = 0;
143     NSFont* loadedFont = 0;
144     loadFont(m_font, m_size, loadedFont, cgFont);
145     
146 #if PLATFORM(CHROMIUM) && OS(DARWIN)
147     // If loadFont replaced m_font with a fallback font, then release the
148     // previous font to counter the retain above. Then retain the new font.
149     if (loadedFont != m_font) {
150         CFRelease(m_font);
151         CFRetain(loadedFont);
152         m_font = loadedFont;
153     }
154 #endif
155     
156 #ifndef BUILDING_ON_TIGER
157     m_cgFont.adoptCF(cgFont);
158 #else
159     m_cgFont = cgFont;
160 #endif
161 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
162     m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait;
163 #endif
164     m_CTFont = 0;
165 }
166
167 bool FontPlatformData::roundsGlyphAdvances() const
168 {
169     return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
170 }
171
172 bool FontPlatformData::allowsLigatures() const
173 {
174     return ![[m_font coveredCharacterSet] characterIsMember:'a'];
175 }
176
177 inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant)
178 {
179     switch(variant) {
180     case RegularWidth:
181         return TextSpacingProportional;
182
183     case HalfWidth:
184         return TextSpacingHalfWidth;
185
186     case ThirdWidth:
187         return TextSpacingThirdWidth;
188
189     case QuarterWidth:
190         return TextSpacingQuarterWidth;
191     }
192
193     ASSERT_NOT_REACHED();
194     return TextSpacingProportional;
195 }
196
197 CTFontRef FontPlatformData::ctFont() const
198 {
199     if (m_widthVariant == RegularWidth) {
200         if (m_font)
201             return toCTFontRef(m_font);
202         if (!m_CTFont)
203             m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
204         return m_CTFont.get();
205     }
206     
207     if (!m_CTFont) {
208         int featureTypeValue = kTextSpacingType;
209         int featureSelectorValue = mapFontWidthVariantToCTFeatureSelector(m_widthVariant);
210         RetainPtr<CTFontRef> sourceFont(AdoptCF, CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
211         RetainPtr<CTFontDescriptorRef> sourceDescriptor(AdoptCF, CTFontCopyFontDescriptor(sourceFont.get()));
212         RetainPtr<CFNumberRef> featureType(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureTypeValue));
213         RetainPtr<CFNumberRef> featureSelector(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorValue));
214         RetainPtr<CTFontDescriptorRef> newDescriptor(AdoptCF, CTFontDescriptorCreateCopyWithFeature(sourceDescriptor.get(), featureType.get(), featureSelector.get()));
215         RetainPtr<CTFontRef> newFont(AdoptCF, CTFontCreateWithFontDescriptor(newDescriptor.get(), m_size, 0));
216
217         m_CTFont = newFont.get() ? newFont : sourceFont;
218     }
219     return m_CTFont.get();
220 }
221
222 #ifndef NDEBUG
223 String FontPlatformData::description() const
224 {
225     RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont()));
226     return String(cgFontDescription.get()) + " " + String::number(m_size)
227             + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : "") + (m_orientation ? " vertical orientation" : "");
228 }
229 #endif
230
231 } // namespace WebCore