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"
36 #include <wtf/MathExtras.h>
37 #include <wtf/UnusedParam.h>
43 SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback)
46 , m_platformData(platformData)
47 , m_treatAsFixedPitch(false)
48 , m_isCustomFont(isCustomFont)
49 , m_isLoading(isLoading)
50 , m_isTextOrientationFallback(isTextOrientationFallback)
51 , m_isBrokenIdeographFallback(false)
52 , m_hasVerticalGlyphs(false)
56 platformCharWidthInit();
59 SimpleFontData::SimpleFontData(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
60 : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic))
61 , m_fontData(fontData)
62 , m_treatAsFixedPitch(false)
63 , m_isCustomFont(true)
65 , m_isTextOrientationFallback(false)
66 , m_isBrokenIdeographFallback(false)
67 , m_hasVerticalGlyphs(false)
69 m_fontData->initializeFontData(this, fontSize);
72 #if !(PLATFORM(QT) && !HAVE(QRAWFONT))
73 // Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
74 void SimpleFontData::initCharWidths()
76 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
78 // Treat the width of a '0' as the avgCharWidth.
79 if (m_avgCharWidth <= 0.f && glyphPageZero) {
80 static const UChar32 digitZeroChar = '0';
81 Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
83 m_avgCharWidth = widthForGlyph(digitZeroGlyph);
86 // If we can't retrieve the width of a '0', fall back to the x height.
87 if (m_avgCharWidth <= 0.f)
88 m_avgCharWidth = m_fontMetrics.xHeight();
90 if (m_maxCharWidth <= 0.f)
91 m_maxCharWidth = max(m_avgCharWidth, m_fontMetrics.floatAscent());
94 void SimpleFontData::platformGlyphInit()
96 GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
98 LOG_ERROR("Failed to get glyph page zero.");
101 m_adjustedSpaceWidth = 0;
103 m_zeroWidthSpaceGlyph = 0;
104 m_missingGlyphData.fontData = this;
105 m_missingGlyphData.glyph = 0;
109 m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
111 // Nasty hack to determine if we should round or ceil space widths.
112 // If the font is monospace or fake monospace we ceil to ensure that
113 // every character and the space are the same width. Otherwise we round.
114 m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
115 float width = widthForGlyph(m_spaceGlyph);
116 m_spaceWidth = width;
118 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
120 // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
121 // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
122 // See <http://bugs.webkit.org/show_bug.cgi?id=13178>
123 // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
124 // are mapped to the ZERO WIDTH SPACE glyph.
125 if (m_zeroWidthSpaceGlyph == m_spaceGlyph) {
126 m_zeroWidthSpaceGlyph = 0;
127 LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden.");
130 m_missingGlyphData.fontData = this;
131 m_missingGlyphData.glyph = 0;
135 SimpleFontData::~SimpleFontData()
137 #if ENABLE(SVG_FONTS)
143 GlyphPageTreeNode::pruneTreeFontData(this);
146 const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
151 bool SimpleFontData::isSegmented() const
156 SimpleFontData* SimpleFontData::verticalRightOrientationFontData() const
158 if (!m_derivedFontData)
159 m_derivedFontData = DerivedFontData::create(isCustomFont());
160 if (!m_derivedFontData->verticalRightOrientation) {
161 FontPlatformData verticalRightPlatformData(m_platformData);
162 verticalRightPlatformData.setOrientation(Horizontal);
163 m_derivedFontData->verticalRightOrientation = adoptPtr(new SimpleFontData(verticalRightPlatformData, isCustomFont(), false, true));
165 return m_derivedFontData->verticalRightOrientation.get();
168 SimpleFontData* SimpleFontData::uprightOrientationFontData() const
170 if (!m_derivedFontData)
171 m_derivedFontData = DerivedFontData::create(isCustomFont());
172 if (!m_derivedFontData->uprightOrientation)
173 m_derivedFontData->uprightOrientation = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false, true));
174 return m_derivedFontData->uprightOrientation.get();
177 SimpleFontData* SimpleFontData::brokenIdeographFontData() const
179 if (!m_derivedFontData)
180 m_derivedFontData = DerivedFontData::create(isCustomFont());
181 if (!m_derivedFontData->brokenIdeograph) {
182 m_derivedFontData->brokenIdeograph = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false));
183 m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
185 return m_derivedFontData->brokenIdeograph.get();
189 String SimpleFontData::description() const
194 return "[custom font]";
196 return platformData().description();
200 PassOwnPtr<SimpleFontData::DerivedFontData> SimpleFontData::DerivedFontData::create(bool forCustomFont)
202 return adoptPtr(new DerivedFontData(forCustomFont));
205 SimpleFontData::DerivedFontData::~DerivedFontData()
211 GlyphPageTreeNode::pruneTreeCustomFontData(smallCaps.get());
213 GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get());
215 GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get());
216 if (verticalRightOrientation)
217 GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get());
218 if (uprightOrientation)
219 GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get());
221 if (compositeFontReferences) {
222 CFDictionaryRef dictionary = CFDictionaryRef(compositeFontReferences.get());
223 CFIndex count = CFDictionaryGetCount(dictionary);
225 Vector<SimpleFontData*, 2> stash(count);
226 SimpleFontData** fonts = stash.data();
227 CFDictionaryGetKeysAndValues(dictionary, 0, (const void **)fonts);
228 while (count-- > 0 && *fonts) {
229 OwnPtr<SimpleFontData> afont = adoptPtr(*fonts++);
230 GlyphPageTreeNode::pruneTreeCustomFontData(afont.get());
237 } // namespace WebCore