1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2000 Dirk Mueller (mueller (at) 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 "FloatRect.h" 28 #include "FontCache.h" 29 #include "FontFallbackList.h" 30 #include "IntPoint.h" 31 #include "GlyphBuffer.h" 32 #include "WidthIterator.h" 33 #include <wtf/MathExtras.h> 34 #include <wtf/UnusedParam.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 60 Font::Font() 61 : m_letterSpacing(0) 62 , m_wordSpacing(0) 63 , m_isPlatformFont(false) 64 { 65 } 66 67 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) 68 : m_fontDescription(fd) 69 , m_letterSpacing(letterSpacing) 70 , m_wordSpacing(wordSpacing) 71 , m_isPlatformFont(false) 72 { 73 } 74 75 Font::Font(const FontPlatformData& fontData, bool isPrinterFont) 76 : m_fontList(FontFallbackList::create()) 77 , m_letterSpacing(0) 78 , m_wordSpacing(0) 79 , m_isPlatformFont(true) 80 { 81 m_fontDescription.setUsePrinterFont(isPrinterFont); 82 m_fontList->setPlatformFont(fontData); 83 } 84 85 Font::Font(const Font& other) 86 : m_fontDescription(other.m_fontDescription) 87 , m_fontList(other.m_fontList) 88 , m_letterSpacing(other.m_letterSpacing) 89 , m_wordSpacing(other.m_wordSpacing) 90 , m_isPlatformFont(other.m_isPlatformFont) 91 { 92 } 93 94 Font& Font::operator=(const Font& other) 95 { 96 m_fontDescription = other.m_fontDescription; 97 m_fontList = other.m_fontList; 98 m_letterSpacing = other.m_letterSpacing; 99 m_wordSpacing = other.m_wordSpacing; 100 m_isPlatformFont = other.m_isPlatformFont; 101 return *this; 102 } 103 104 Font::~Font() 105 { 106 } 107 108 bool Font::operator==(const Font& other) const 109 { 110 // Our FontData don't have to be checked, since checking the font description will be fine. 111 // FIXME: This does not work if the font was made with the FontPlatformData constructor. 112 if ((m_fontList && m_fontList->loadingCustomFonts()) || 113 (other.m_fontList && other.m_fontList->loadingCustomFonts())) 114 return false; 115 116 FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0; 117 FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0; 118 119 return first == second 120 && m_fontDescription == other.m_fontDescription 121 && m_letterSpacing == other.m_letterSpacing 122 && m_wordSpacing == other.m_wordSpacing 123 && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0); 124 } 125 126 const SimpleFontData* Font::primaryFont() const 127 { 128 ASSERT(m_fontList); 129 return m_fontList->primarySimpleFontData(this); 130 } 131 132 const FontData* Font::fontDataAt(unsigned index) const 133 { 134 ASSERT(m_fontList); 135 return m_fontList->fontDataAt(this, index); 136 } 137 138 const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const 139 { 140 ASSERT(m_fontList); 141 return m_fontList->fontDataForCharacters(this, characters, length); 142 } 143 144 void Font::update(PassRefPtr<FontSelector> fontSelector) const 145 { 146 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up 147 // being reasonably safe (because inherited fonts in the render tree pick up the new 148 // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and 149 // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, 150 // and could eventually be rectified by using RefPtrs for Fonts themselves. 151 if (!m_fontList) 152 m_fontList = FontFallbackList::create(); 153 m_fontList->invalidate(fontSelector); 154 } 155 156 bool Font::isFixedPitch() const 157 { 158 ASSERT(m_fontList); 159 return m_fontList->isFixedPitch(this); 160 } 161 162 void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 163 { 164 // Don't draw anything while we are using custom fonts that are in the process of loading. 165 if (m_fontList && m_fontList->loadingCustomFonts()) 166 return; 167 168 to = (to == -1 ? run.length() : to); 169 170 #if ENABLE(SVG_FONTS) 171 if (primaryFont()->isSVGFont()) { 172 drawTextUsingSVGFont(context, run, point, from, to); 173 return; 174 } 175 #endif 176 177 #if USE(FONT_FAST_PATH) 178 if (canUseGlyphCache(run)) 179 return drawSimpleText(context, run, point, from, to); 180 #endif 181 182 return drawComplexText(context, run, point, from, to); 183 } 184 185 float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const 186 { 187 #if ENABLE(SVG_FONTS) 188 if (primaryFont()->isSVGFont()) 189 return floatWidthUsingSVGFont(run); 190 #endif 191 192 #if USE(FONT_FAST_PATH) 193 if (canUseGlyphCache(run)) { 194 // If the complex text implementation cannot return fallback fonts, avoid 195 // returning them for simple text as well. 196 static bool returnFallbackFonts = canReturnFallbackFontsForComplexText(); 197 return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0); 198 } 199 #endif 200 201 return floatWidthForComplexText(run, fallbackFonts); 202 } 203 204 float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const 205 { 206 #if !ENABLE(SVG_FONTS) 207 UNUSED_PARAM(extraCharsAvailable); 208 #else 209 if (primaryFont()->isSVGFont()) 210 return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName); 211 #endif 212 213 charsConsumed = run.length(); 214 glyphName = ""; 215 216 #if USE(FONT_FAST_PATH) 217 if (canUseGlyphCache(run)) 218 return floatWidthForSimpleText(run, 0); 219 #endif 220 221 return floatWidthForComplexText(run); 222 } 223 224 FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const 225 { 226 #if ENABLE(SVG_FONTS) 227 if (primaryFont()->isSVGFont()) 228 return selectionRectForTextUsingSVGFont(run, point, h, from, to); 229 #endif 230 231 to = (to == -1 ? run.length() : to); 232 233 #if USE(FONT_FAST_PATH) 234 if (canUseGlyphCache(run)) 235 return selectionRectForSimpleText(run, point, h, from, to); 236 #endif 237 238 return selectionRectForComplexText(run, point, h, from, to); 239 } 240 241 int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const 242 { 243 #if ENABLE(SVG_FONTS) 244 if (primaryFont()->isSVGFont()) 245 return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs); 246 #endif 247 248 #if USE(FONT_FAST_PATH) 249 if (canUseGlyphCache(run)) 250 return offsetForPositionForSimpleText(run, x, includePartialGlyphs); 251 #endif 252 253 return offsetForPositionForComplexText(run, x, includePartialGlyphs); 254 } 255 256 #if ENABLE(SVG_FONTS) 257 bool Font::isSVGFont() const 258 { 259 return primaryFont()->isSVGFont(); 260 } 261 #endif 262 263 FontSelector* Font::fontSelector() const 264 { 265 return m_fontList ? m_fontList->fontSelector() : 0; 266 } 267 268 String Font::normalizeSpaces(const String& string) 269 { 270 unsigned length = string.length(); 271 Vector<UChar, 256> buffer(length); 272 bool didReplacement = false; 273 274 for (unsigned i = 0; i < length; ++i) { 275 UChar originalCharacter = string[i]; 276 buffer[i] = normalizeSpaces(originalCharacter); 277 if (buffer[i] != originalCharacter) 278 didReplacement = true; 279 } 280 281 return didReplacement ? String(buffer.data(), length) : string; 282 } 283 284 static bool shouldUseFontSmoothing = true; 285 286 void Font::setShouldUseSmoothing(bool shouldUseSmoothing) 287 { 288 ASSERT(isMainThread()); 289 shouldUseFontSmoothing = shouldUseSmoothing; 290 } 291 292 bool Font::shouldUseSmoothing() 293 { 294 return shouldUseFontSmoothing; 295 } 296 297 } 298