2 * Copyright (C) 2005, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "SimpleFontData.h"
34 #include "FontCache.h"
35 #include "OpenTypeVerticalData.h"
37 #include <wtf/MathExtras.h>
38 #include <wtf/UnusedParam.h>
44 const float smallCapsFontSizeMultiplier = 0.7f;
45 const float emphasisMarkFontSizeMultiplier = 0.5f;
47 SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback)
50 , m_platformData(platformData)
51 , m_treatAsFixedPitch(false)
52 , m_isCustomFont(isCustomFont)
53 , m_isLoading(isLoading)
54 , m_isTextOrientationFallback(isTextOrientationFallback)
55 , m_isBrokenIdeographFallback(false)
56 #if ENABLE(OPENTYPE_VERTICAL)
59 , m_hasVerticalGlyphs(false)
63 platformCharWidthInit();
64 #if ENABLE(OPENTYPE_VERTICAL)
65 if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
66 m_verticalData = platformData.verticalData();
67 m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
72 SimpleFontData::SimpleFontData(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
73 : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic))
74 , m_fontData(fontData)
75 , m_treatAsFixedPitch(false)
76 , m_isCustomFont(true)
78 , m_isTextOrientationFallback(false)
79 , m_isBrokenIdeographFallback(false)
80 #if ENABLE(OPENTYPE_VERTICAL)
83 , m_hasVerticalGlyphs(false)
85 m_fontData->initializeFontData(this, fontSize);
88 // Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
89 void SimpleFontData::initCharWidths()
91 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
93 // Treat the width of a '0' as the avgCharWidth.
94 if (m_avgCharWidth <= 0.f && glyphPageZero) {
95 static const UChar32 digitZeroChar = '0';
96 Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
98 m_avgCharWidth = widthForGlyph(digitZeroGlyph);
101 // If we can't retrieve the width of a '0', fall back to the x height.
102 if (m_avgCharWidth <= 0.f)
103 m_avgCharWidth = m_fontMetrics.xHeight();
105 if (m_maxCharWidth <= 0.f)
106 m_maxCharWidth = max(m_avgCharWidth, m_fontMetrics.floatAscent());
109 void SimpleFontData::platformGlyphInit()
111 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
112 if (!glyphPageZero) {
113 LOG_ERROR("Failed to get glyph page zero.");
117 m_adjustedSpaceWidth = 0;
119 m_zeroWidthSpaceGlyph = 0;
120 m_missingGlyphData.fontData = this;
121 m_missingGlyphData.glyph = 0;
125 m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
127 // Nasty hack to determine if we should round or ceil space widths.
128 // If the font is monospace or fake monospace we ceil to ensure that
129 // every character and the space are the same width. Otherwise we round.
130 m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
131 float width = widthForGlyph(m_spaceGlyph);
132 m_spaceWidth = width;
133 m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
134 m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
136 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
138 // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
139 // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
140 // See <http://bugs.webkit.org/show_bug.cgi?id=13178>
141 // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
142 // are mapped to the ZERO WIDTH SPACE glyph.
143 if (m_zeroWidthSpaceGlyph == m_spaceGlyph) {
144 m_zeroWidthSpaceGlyph = 0;
145 LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden.");
148 m_missingGlyphData.fontData = this;
149 m_missingGlyphData.glyph = 0;
152 SimpleFontData::~SimpleFontData()
154 #if ENABLE(SVG_FONTS)
160 GlyphPageTreeNode::pruneTreeCustomFontData(this);
162 GlyphPageTreeNode::pruneTreeFontData(this);
165 const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
170 Glyph SimpleFontData::glyphForCharacter(UChar32 character) const
172 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(this, character / GlyphPage::size);
173 return node->page() ? node->page()->glyphAt(character % GlyphPage::size) : 0;
176 bool SimpleFontData::isSegmented() const
181 PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() const
183 if (!m_derivedFontData)
184 m_derivedFontData = DerivedFontData::create(isCustomFont());
185 if (!m_derivedFontData->verticalRightOrientation) {
186 FontPlatformData verticalRightPlatformData(m_platformData);
187 verticalRightPlatformData.setOrientation(Horizontal);
188 m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont(), false, true);
190 return m_derivedFontData->verticalRightOrientation;
193 PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const
195 if (!m_derivedFontData)
196 m_derivedFontData = DerivedFontData::create(isCustomFont());
197 if (!m_derivedFontData->uprightOrientation)
198 m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont(), false, true);
199 return m_derivedFontData->uprightOrientation;
202 PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
204 if (!m_derivedFontData)
205 m_derivedFontData = DerivedFontData::create(isCustomFont());
206 if (!m_derivedFontData->smallCaps)
207 m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier);
209 return m_derivedFontData->smallCaps;
212 PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
214 if (!m_derivedFontData)
215 m_derivedFontData = DerivedFontData::create(isCustomFont());
216 if (!m_derivedFontData->emphasisMark)
217 m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFontSizeMultiplier);
219 return m_derivedFontData->emphasisMark;
222 PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const
224 if (!m_derivedFontData)
225 m_derivedFontData = DerivedFontData::create(isCustomFont());
226 if (!m_derivedFontData->brokenIdeograph) {
227 m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont(), false);
228 m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
230 return m_derivedFontData->brokenIdeograph;
234 String SimpleFontData::description() const
239 return "[custom font]";
241 return platformData().description();
245 PassOwnPtr<SimpleFontData::DerivedFontData> SimpleFontData::DerivedFontData::create(bool forCustomFont)
247 return adoptPtr(new DerivedFontData(forCustomFont));
250 SimpleFontData::DerivedFontData::~DerivedFontData()
256 GlyphPageTreeNode::pruneTreeCustomFontData(smallCaps.get());
258 GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get());
260 GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get());
261 if (verticalRightOrientation)
262 GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get());
263 if (uprightOrientation)
264 GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get());
266 if (compositeFontReferences) {
267 CFDictionaryRef dictionary = CFDictionaryRef(compositeFontReferences.get());
268 CFIndex count = CFDictionaryGetCount(dictionary);
270 Vector<SimpleFontData*, 2> stash(count);
271 SimpleFontData** fonts = stash.data();
272 CFDictionaryGetKeysAndValues(dictionary, 0, (const void **)fonts);
273 while (count-- > 0 && *fonts) {
274 OwnPtr<SimpleFontData> afont = adoptPtr(*fonts++);
275 GlyphPageTreeNode::pruneTreeCustomFontData(afont.get());
282 } // namespace WebCore