1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2003, 2006 Apple 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 #include "config.h" 25 #include "Font.h" 26 27 #include "CharacterNames.h" 28 #include "FloatRect.h" 29 #include "FontCache.h" 30 #include "FontFallbackList.h" 31 #include "IntPoint.h" 32 #include "GlyphBuffer.h" 33 #include "WidthIterator.h" 34 #include <wtf/MathExtras.h> 35 36 using namespace WTF; 37 using namespace Unicode; 38 39 namespace WebCore { 40 41 #if USE(FONT_FAST_PATH) 42 const uint8_t Font::gRoundingHackCharacterTable[256] = { 43 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/, 45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 51 }; 52 53 Font::CodePath Font::s_codePath = Auto; 54 #endif 55 56 // ============================================================================================ 57 // Font Implementation (Cross-Platform Portion) 58 // ============================================================================================ 59 Font()60 Font::Font() 61 : m_pageZero(0) 62 , m_cachedPrimaryFont(0) 63 , m_letterSpacing(0) 64 , m_wordSpacing(0) 65 , m_isPlatformFont(false) 66 { 67 } 68 Font(const FontDescription & fd,short letterSpacing,short wordSpacing)69 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) 70 : m_fontDescription(fd) 71 , m_pageZero(0) 72 , m_cachedPrimaryFont(0) 73 , m_letterSpacing(letterSpacing) 74 , m_wordSpacing(wordSpacing) 75 , m_isPlatformFont(false) 76 { 77 } 78 Font(const FontPlatformData & fontData,bool isPrinterFont)79 Font::Font(const FontPlatformData& fontData, bool isPrinterFont) 80 : m_fontList(FontFallbackList::create()) 81 , m_pageZero(0) 82 , m_cachedPrimaryFont(0) 83 , m_letterSpacing(0) 84 , m_wordSpacing(0) 85 , m_isPlatformFont(true) 86 { 87 m_fontDescription.setUsePrinterFont(isPrinterFont); 88 m_fontList->setPlatformFont(fontData); 89 } 90 Font(const Font & other)91 Font::Font(const Font& other) 92 : m_fontDescription(other.m_fontDescription) 93 , m_fontList(other.m_fontList) 94 , m_pages(other.m_pages) 95 , m_pageZero(other.m_pageZero) 96 , m_cachedPrimaryFont(other.m_cachedPrimaryFont) 97 , m_letterSpacing(other.m_letterSpacing) 98 , m_wordSpacing(other.m_wordSpacing) 99 , m_isPlatformFont(other.m_isPlatformFont) 100 { 101 } 102 operator =(const Font & other)103 Font& Font::operator=(const Font& other) 104 { 105 m_fontDescription = other.m_fontDescription; 106 m_fontList = other.m_fontList; 107 m_pages = other.m_pages; 108 m_pageZero = other.m_pageZero; 109 m_cachedPrimaryFont = other.m_cachedPrimaryFont; 110 m_letterSpacing = other.m_letterSpacing; 111 m_wordSpacing = other.m_wordSpacing; 112 m_isPlatformFont = other.m_isPlatformFont; 113 return *this; 114 } 115 ~Font()116 Font::~Font() 117 { 118 } 119 operator ==(const Font & other) const120 bool Font::operator==(const Font& other) const 121 { 122 // Our FontData don't have to be checked, since checking the font description will be fine. 123 // FIXME: This does not work if the font was made with the FontPlatformData constructor. 124 if ((m_fontList && m_fontList->loadingCustomFonts()) || 125 (other.m_fontList && other.m_fontList->loadingCustomFonts())) 126 return false; 127 128 FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0; 129 FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0; 130 131 return first == second 132 && m_fontDescription == other.m_fontDescription 133 && m_letterSpacing == other.m_letterSpacing 134 && m_wordSpacing == other.m_wordSpacing 135 && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0); 136 } 137 cachePrimaryFont() const138 void Font::cachePrimaryFont() const 139 { 140 ASSERT(m_fontList); 141 ASSERT(!m_cachedPrimaryFont); 142 m_cachedPrimaryFont = m_fontList->primaryFont(this)->fontDataForCharacter(' '); 143 } 144 fontDataAt(unsigned index) const145 const FontData* Font::fontDataAt(unsigned index) const 146 { 147 ASSERT(m_fontList); 148 return m_fontList->fontDataAt(this, index); 149 } 150 fontDataForCharacters(const UChar * characters,int length) const151 const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const 152 { 153 ASSERT(m_fontList); 154 return m_fontList->fontDataForCharacters(this, characters, length); 155 } 156 update(PassRefPtr<FontSelector> fontSelector) const157 void Font::update(PassRefPtr<FontSelector> fontSelector) const 158 { 159 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up 160 // being reasonably safe (because inherited fonts in the render tree pick up the new 161 // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and 162 // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, 163 // and could eventually be rectified by using RefPtrs for Fonts themselves. 164 if (!m_fontList) 165 m_fontList = FontFallbackList::create(); 166 m_fontList->invalidate(fontSelector); 167 m_cachedPrimaryFont = 0; 168 m_pageZero = 0; 169 m_pages.clear(); 170 } 171 isFixedPitch() const172 bool Font::isFixedPitch() const 173 { 174 ASSERT(m_fontList); 175 return m_fontList->isFixedPitch(this); 176 } 177 drawText(GraphicsContext * context,const TextRun & run,const FloatPoint & point,int from,int to) const178 void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 179 { 180 // Don't draw anything while we are using custom fonts that are in the process of loading. 181 if (m_fontList && m_fontList->loadingCustomFonts()) 182 return; 183 184 to = (to == -1 ? run.length() : to); 185 186 #if ENABLE(SVG_FONTS) 187 if (primaryFont()->isSVGFont()) { 188 drawTextUsingSVGFont(context, run, point, from, to); 189 return; 190 } 191 #endif 192 193 #if USE(FONT_FAST_PATH) 194 if (canUseGlyphCache(run)) 195 return drawSimpleText(context, run, point, from, to); 196 #endif 197 198 return drawComplexText(context, run, point, from, to); 199 } 200 floatWidth(const TextRun & run) const201 float Font::floatWidth(const TextRun& run) const 202 { 203 #if ENABLE(SVG_FONTS) 204 if (primaryFont()->isSVGFont()) 205 return floatWidthUsingSVGFont(run); 206 #endif 207 208 #if USE(FONT_FAST_PATH) 209 if (canUseGlyphCache(run)) 210 return floatWidthForSimpleText(run, 0); 211 #endif 212 213 return floatWidthForComplexText(run); 214 } 215 floatWidth(const TextRun & run,int extraCharsAvailable,int & charsConsumed,String & glyphName) const216 float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const 217 { 218 #if ENABLE(SVG_FONTS) 219 if (primaryFont()->isSVGFont()) 220 return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName); 221 #endif 222 223 charsConsumed = run.length(); 224 glyphName = ""; 225 226 #if USE(FONT_FAST_PATH) 227 if (canUseGlyphCache(run)) 228 return floatWidthForSimpleText(run, 0); 229 #endif 230 231 return floatWidthForComplexText(run); 232 } 233 selectionRectForText(const TextRun & run,const IntPoint & point,int h,int from,int to) const234 FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const 235 { 236 #if ENABLE(SVG_FONTS) 237 if (primaryFont()->isSVGFont()) 238 return selectionRectForTextUsingSVGFont(run, point, h, from, to); 239 #endif 240 241 to = (to == -1 ? run.length() : to); 242 243 #if USE(FONT_FAST_PATH) 244 if (canUseGlyphCache(run)) 245 return selectionRectForSimpleText(run, point, h, from, to); 246 #endif 247 248 return selectionRectForComplexText(run, point, h, from, to); 249 } 250 offsetForPosition(const TextRun & run,int x,bool includePartialGlyphs) const251 int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const 252 { 253 #if ENABLE(SVG_FONTS) 254 if (primaryFont()->isSVGFont()) 255 return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs); 256 #endif 257 258 #if USE(FONT_FAST_PATH) 259 if (canUseGlyphCache(run)) 260 return offsetForPositionForSimpleText(run, x, includePartialGlyphs); 261 #endif 262 263 return offsetForPositionForComplexText(run, x, includePartialGlyphs); 264 } 265 266 #if ENABLE(SVG_FONTS) isSVGFont() const267 bool Font::isSVGFont() const 268 { 269 return primaryFont()->isSVGFont(); 270 } 271 #endif 272 fontSelector() const273 FontSelector* Font::fontSelector() const 274 { 275 return m_fontList ? m_fontList->fontSelector() : 0; 276 } 277 278 } 279