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, 2010, 2011 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 "platform/fonts/Font.h" 26 27 #include "platform/LayoutUnit.h" 28 #include "platform/fonts/Character.h" 29 #include "platform/fonts/FontCache.h" 30 #include "platform/fonts/FontFallbackList.h" 31 #include "platform/fonts/FontPlatformFeatures.h" 32 #include "platform/fonts/GlyphBuffer.h" 33 #include "platform/fonts/GlyphPageTreeNode.h" 34 #include "platform/fonts/SimpleFontData.h" 35 #include "platform/fonts/WidthIterator.h" 36 #include "platform/geometry/FloatRect.h" 37 #include "platform/text/TextRun.h" 38 #include "wtf/MainThread.h" 39 #include "wtf/StdLibExtras.h" 40 #include "wtf/unicode/CharacterNames.h" 41 #include "wtf/unicode/Unicode.h" 42 43 using namespace WTF; 44 using namespace Unicode; 45 using namespace std; 46 47 namespace WebCore { 48 49 CodePath Font::s_codePath = AutoPath; 50 51 // ============================================================================================ 52 // Font Implementation (Cross-Platform Portion) 53 // ============================================================================================ 54 55 Font::Font() 56 { 57 } 58 59 Font::Font(const FontDescription& fd) 60 : m_fontDescription(fd) 61 { 62 } 63 64 Font::Font(const Font& other) 65 : m_fontDescription(other.m_fontDescription) 66 , m_fontFallbackList(other.m_fontFallbackList) 67 { 68 } 69 70 Font& Font::operator=(const Font& other) 71 { 72 m_fontDescription = other.m_fontDescription; 73 m_fontFallbackList = other.m_fontFallbackList; 74 return *this; 75 } 76 77 bool Font::operator==(const Font& other) const 78 { 79 // Our FontData don't have to be checked, since checking the font description will be fine. 80 // FIXME: This does not work if the font was made with the FontPlatformData constructor. 81 if (loadingCustomFonts() || other.loadingCustomFonts()) 82 return false; 83 84 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; 85 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0; 86 87 return first == second 88 && m_fontDescription == other.m_fontDescription 89 && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0) 90 && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0); 91 } 92 93 void Font::update(PassRefPtrWillBeRawPtr<FontSelector> fontSelector) const 94 { 95 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up 96 // being reasonably safe (because inherited fonts in the render tree pick up the new 97 // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and 98 // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, 99 // and could eventually be rectified by using RefPtrs for Fonts themselves. 100 if (!m_fontFallbackList) 101 m_fontFallbackList = FontFallbackList::create(); 102 m_fontFallbackList->invalidate(fontSelector); 103 } 104 105 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const 106 { 107 // Don't draw anything while we are using custom fonts that are in the process of loading, 108 // except if the 'force' argument is set to true (in which case it will use a fallback 109 // font). 110 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotReady) 111 return; 112 113 CodePath codePathToUse = codePath(runInfo.run); 114 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 115 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) 116 codePathToUse = ComplexPath; 117 118 if (codePathToUse != ComplexPath) 119 return drawSimpleText(context, runInfo, point); 120 121 return drawComplexText(context, runInfo, point); 122 } 123 124 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const 125 { 126 if (shouldSkipDrawing()) 127 return; 128 129 CodePath codePathToUse = codePath(runInfo.run); 130 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 131 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) 132 codePathToUse = ComplexPath; 133 134 if (codePathToUse != ComplexPath) 135 drawEmphasisMarksForSimpleText(context, runInfo, mark, point); 136 else 137 drawEmphasisMarksForComplexText(context, runInfo, mark, point); 138 } 139 140 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBounds, 141 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) 142 { 143 glyphOverflow->top = max<int>(glyphOverflow->top, 144 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.ascent())); 145 glyphOverflow->bottom = max<int>(glyphOverflow->bottom, 146 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.descent())); 147 glyphOverflow->left = glyphBounds.left(); 148 glyphOverflow->right = glyphBounds.right(); 149 } 150 151 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const 152 { 153 CodePath codePathToUse = codePath(run); 154 if (codePathToUse != ComplexPath) { 155 // The complex path is more restrictive about returning fallback fonts than the simple path, so we need an explicit test to make their behaviors match. 156 if (!FontPlatformFeatures::canReturnFallbackFontsForComplexText()) 157 fallbackFonts = 0; 158 // The simple path can optimize the case where glyph overflow is not observable. 159 if (codePathToUse != SimpleWithGlyphOverflowPath && (glyphOverflow && !glyphOverflow->computeBounds)) 160 glyphOverflow = 0; 161 } 162 163 bool hasKerningOrLigatures = fontDescription().typesettingFeatures() & (Kerning | Ligatures); 164 bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() || fontDescription().letterSpacing(); 165 bool isCacheable = (codePathToUse == ComplexPath || hasKerningOrLigatures) 166 && !hasWordSpacingOrLetterSpacing // Word spacing and letter spacing can change the width of a word. 167 && !run.allowTabs(); // If we allow tabs and a tab occurs inside a word, the width of the word varies based on its position on the line. 168 169 WidthCacheEntry* cacheEntry = isCacheable 170 ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry()) 171 : 0; 172 if (cacheEntry && cacheEntry->isValid()) { 173 if (glyphOverflow) 174 updateGlyphOverflowFromBounds(cacheEntry->glyphBounds, fontMetrics(), glyphOverflow); 175 return cacheEntry->width; 176 } 177 178 float result; 179 IntRectExtent glyphBounds; 180 if (codePathToUse == ComplexPath) { 181 result = floatWidthForComplexText(run, fallbackFonts, &glyphBounds); 182 } else { 183 result = floatWidthForSimpleText(run, fallbackFonts, 184 glyphOverflow || isCacheable ? &glyphBounds : 0); 185 } 186 187 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { 188 cacheEntry->glyphBounds = glyphBounds; 189 cacheEntry->width = result; 190 } 191 192 if (glyphOverflow) 193 updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow); 194 return result; 195 } 196 197 float Font::width(const TextRun& run, int& charsConsumed, Glyph& glyphId) const 198 { 199 #if ENABLE(SVG_FONTS) 200 if (TextRun::RenderingContext* renderingContext = run.renderingContext()) 201 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphId); 202 #endif 203 204 charsConsumed = run.length(); 205 glyphId = 0; 206 return width(run); 207 } 208 209 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to, bool accountForGlyphBounds) const 210 { 211 to = (to == -1 ? run.length() : to); 212 213 CodePath codePathToUse = codePath(run); 214 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 215 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length())) 216 codePathToUse = ComplexPath; 217 218 if (codePathToUse != ComplexPath) 219 return selectionRectForSimpleText(run, point, h, from, to, accountForGlyphBounds); 220 221 return selectionRectForComplexText(run, point, h, from, to); 222 } 223 224 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const 225 { 226 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 227 if (codePath(run) != ComplexPath && !fontDescription().typesettingFeatures()) 228 return offsetForPositionForSimpleText(run, x, includePartialGlyphs); 229 230 return offsetForPositionForComplexText(run, x, includePartialGlyphs); 231 } 232 233 void Font::setCodePath(CodePath p) 234 { 235 s_codePath = p; 236 } 237 238 CodePath Font::codePath() 239 { 240 return s_codePath; 241 } 242 243 CodePath Font::codePath(const TextRun& run) const 244 { 245 if (s_codePath != AutoPath) 246 return s_codePath; 247 248 #if ENABLE(SVG_FONTS) 249 if (run.renderingContext()) 250 return SimplePath; 251 #endif 252 253 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0 && m_fontDescription.letterSpacing() == 0) 254 return ComplexPath; 255 256 if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this)) 257 return ComplexPath; 258 259 if (!run.characterScanForCodePath()) 260 return SimplePath; 261 262 if (run.is8Bit()) 263 return SimplePath; 264 265 // Start from 0 since drawing and highlighting also measure the characters before run->from. 266 return Character::characterRangeCodePath(run.characters16(), run.length()); 267 } 268 269 void Font::willUseFontData(UChar32 character) const 270 { 271 const FontFamily& family = fontDescription().family(); 272 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty()) 273 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family(), character); 274 } 275 276 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound) 277 { 278 return character >= lowerBound && character <= upperBound; 279 } 280 281 static bool shouldIgnoreRotation(UChar32 character) 282 { 283 if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE) 284 return true; 285 286 if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE) 287 return true; 288 289 if (isInRange(character, 0x002E5, 0x002EB)) 290 return true; 291 292 if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF)) 293 return true; 294 295 if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021 296 || character == 0x2030 || character == 0x02031) 297 return true; 298 299 if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047 300 || character == 0x02048 || character == 0x02049 || character == 0x2051) 301 return true; 302 303 if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0) 304 || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117) 305 || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F)) 306 return true; 307 308 if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D 309 || isInRange(character, 0x0214F, 0x0218F)) 310 return true; 311 312 if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F) 313 || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A) 314 || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF) 315 || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF)) 316 return true; 317 318 if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767) 319 || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F) 320 || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007)) 321 return true; 322 323 if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F) 324 || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB) 325 || isInRange(character, 0x030FD, 0x0A4CF)) 326 return true; 327 328 if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F) 329 || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF)) 330 return true; 331 332 if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48) 333 || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62) 334 || isInRange(character, 0x0FE67, 0x0FE6F)) 335 return true; 336 337 if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C) 338 || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A)) 339 return true; 340 341 if (character == 0x0FF3C || character == 0x0FF3E) 342 return true; 343 344 if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2) 345 || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8) 346 || character == 0x0FFFD) 347 return true; 348 349 if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF) 350 || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F) 351 || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F)) 352 return true; 353 354 if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD)) 355 return true; 356 357 return false; 358 } 359 360 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber) 361 { 362 if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) { 363 RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData(); 364 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber); 365 GlyphPage* uprightPage = uprightNode->page(); 366 if (uprightPage) { 367 GlyphData uprightData = uprightPage->glyphDataForCharacter(character); 368 // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. 369 if (data.glyph == uprightData.glyph) 370 return make_pair(data, page); 371 // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that 372 // glyph, so we fall back to the upright data and use the horizontal glyph. 373 if (uprightData.fontData) 374 return make_pair(uprightData, uprightPage); 375 } 376 } else if (orientation == NonCJKGlyphOrientationVerticalRight) { 377 RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData(); 378 GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber); 379 GlyphPage* verticalRightPage = verticalRightNode->page(); 380 if (verticalRightPage) { 381 GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character); 382 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked 383 // into it. 384 if (data.glyph != verticalRightData.glyph) 385 return make_pair(data, page); 386 // The glyphs are identical, meaning that we should just use the horizontal glyph. 387 if (verticalRightData.fontData) 388 return make_pair(verticalRightData, verticalRightPage); 389 } 390 } 391 return make_pair(data, page); 392 } 393 394 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const 395 { 396 ASSERT(isMainThread()); 397 398 if (variant == AutoVariant) { 399 if (m_fontDescription.variant() == FontVariantSmallCaps && !primaryFont()->isSVGFont()) { 400 UChar32 upperC = toUpper(c); 401 if (upperC != c) { 402 c = upperC; 403 variant = SmallCapsVariant; 404 } else { 405 variant = NormalVariant; 406 } 407 } else { 408 variant = NormalVariant; 409 } 410 } 411 412 if (mirror) 413 c = mirroredChar(c); 414 415 unsigned pageNumber = (c / GlyphPage::size); 416 417 GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero; 418 if (!node) { 419 node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); 420 if (pageNumber) 421 m_fontFallbackList->m_pages.set(pageNumber, node); 422 else 423 m_fontFallbackList->m_pageZero = node; 424 } 425 426 GlyphPage* page = 0; 427 if (variant == NormalVariant) { 428 // Fastest loop, for the common case (normal variant). 429 while (true) { 430 page = node->page(); 431 if (page) { 432 GlyphData data = page->glyphDataForCharacter(c); 433 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback())) 434 return make_pair(data, page); 435 436 if (data.fontData) { 437 if (Character::isCJKIdeographOrSymbol(c)) { 438 if (!data.fontData->hasVerticalGlyphs()) { 439 // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs 440 // to make sure you get a square (even for broken glyphs like symbols used for punctuation). 441 variant = BrokenIdeographVariant; 442 break; 443 } 444 } else { 445 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); 446 } 447 448 return make_pair(data, page); 449 } 450 451 if (node->isSystemFallback()) 452 break; 453 } 454 455 // Proceed with the fallback list. 456 node = node->getChild(fontDataAt(node->level()), pageNumber); 457 if (pageNumber) 458 m_fontFallbackList->m_pages.set(pageNumber, node); 459 else 460 m_fontFallbackList->m_pageZero = node; 461 } 462 } 463 if (variant != NormalVariant) { 464 while (true) { 465 page = node->page(); 466 if (page) { 467 GlyphData data = page->glyphDataForCharacter(c); 468 if (data.fontData) { 469 // The variantFontData function should not normally return 0. 470 // But if it does, we will just render the capital letter big. 471 RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant); 472 if (!variantFontData) 473 return make_pair(data, page); 474 475 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber); 476 GlyphPage* variantPage = variantNode->page(); 477 if (variantPage) { 478 GlyphData data = variantPage->glyphDataForCharacter(c); 479 if (data.fontData) 480 return make_pair(data, variantPage); 481 } 482 483 // Do not attempt system fallback off the variantFontData. This is the very unlikely case that 484 // a font has the lowercase character but the small caps font does not have its uppercase version. 485 return make_pair(variantFontData->missingGlyphData(), page); 486 } 487 488 if (node->isSystemFallback()) 489 break; 490 } 491 492 // Proceed with the fallback list. 493 node = node->getChild(fontDataAt(node->level()), pageNumber); 494 if (pageNumber) 495 m_fontFallbackList->m_pages.set(pageNumber, node); 496 else 497 m_fontFallbackList->m_pageZero = node; 498 } 499 } 500 501 ASSERT(page); 502 ASSERT(node->isSystemFallback()); 503 504 // System fallback is character-dependent. When we get here, we 505 // know that the character in question isn't in the system fallback 506 // font's glyph page. Try to lazily create it here. 507 508 // FIXME: Unclear if this should normalizeSpaces above 0xFFFF. 509 // Doing so changes fast/text/international/plane2-diffs.html 510 UChar32 characterToRender = c; 511 if (characterToRender <= 0xFFFF) 512 characterToRender = Character::normalizeSpaces(characterToRender); 513 const SimpleFontData* fontDataToSubstitute = fontDataAt(0)->fontDataForCharacter(characterToRender); 514 RefPtr<SimpleFontData> characterFontData = FontCache::fontCache()->fallbackFontForCharacter(m_fontDescription, characterToRender, fontDataToSubstitute); 515 if (characterFontData) { 516 if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Character::isCJKIdeographOrSymbol(c)) 517 variant = BrokenIdeographVariant; 518 if (variant != NormalVariant) 519 characterFontData = characterFontData->variantFontData(m_fontDescription, variant); 520 } 521 if (characterFontData) { 522 // Got the fallback glyph and font. 523 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page(); 524 GlyphData data = fallbackPage && fallbackPage->glyphForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); 525 // Cache it so we don't have to do system fallback again next time. 526 if (variant == NormalVariant) { 527 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 528 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level())); 529 if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback()) 530 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); 531 } 532 return make_pair(data, page); 533 } 534 535 // Even system fallback can fail; use the missing glyph in that case. 536 // FIXME: It would be nicer to use the missing glyph from the last resort font instead. 537 GlyphData data = primaryFont()->missingGlyphData(); 538 if (variant == NormalVariant) { 539 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 540 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level())); 541 } 542 return make_pair(data, page); 543 } 544 545 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const 546 { 547 unsigned pageNumber = (character / GlyphPage::size); 548 549 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber); 550 GlyphPage* page = node->page(); 551 552 return page && page->glyphForCharacter(character); 553 } 554 555 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the 556 // standard emphasis marks do so. 557 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const 558 { 559 if (mark.isEmpty()) 560 return false; 561 562 UChar32 character = mark[0]; 563 564 if (U16_IS_SURROGATE(character)) { 565 if (!U16_IS_SURROGATE_LEAD(character)) 566 return false; 567 568 if (mark.length() < 2) 569 return false; 570 571 UChar low = mark[1]; 572 if (!U16_IS_TRAIL(low)) 573 return false; 574 575 character = U16_GET_SUPPLEMENTARY(character, low); 576 } 577 578 glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant); 579 return true; 580 } 581 582 int Font::emphasisMarkAscent(const AtomicString& mark) const 583 { 584 FontCachePurgePreventer purgePreventer; 585 586 GlyphData markGlyphData; 587 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 588 return 0; 589 590 const SimpleFontData* markFontData = markGlyphData.fontData; 591 ASSERT(markFontData); 592 if (!markFontData) 593 return 0; 594 595 return markFontData->fontMetrics().ascent(); 596 } 597 598 int Font::emphasisMarkDescent(const AtomicString& mark) const 599 { 600 FontCachePurgePreventer purgePreventer; 601 602 GlyphData markGlyphData; 603 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 604 return 0; 605 606 const SimpleFontData* markFontData = markGlyphData.fontData; 607 ASSERT(markFontData); 608 if (!markFontData) 609 return 0; 610 611 return markFontData->fontMetrics().descent(); 612 } 613 614 int Font::emphasisMarkHeight(const AtomicString& mark) const 615 { 616 FontCachePurgePreventer purgePreventer; 617 618 GlyphData markGlyphData; 619 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 620 return 0; 621 622 const SimpleFontData* markFontData = markGlyphData.fontData; 623 ASSERT(markFontData); 624 if (!markFontData) 625 return 0; 626 627 return markFontData->fontMetrics().height(); 628 } 629 630 float Font::getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const 631 { 632 float initialAdvance; 633 634 WidthIterator it(this, runInfo.run, 0, false, forTextEmphasis); 635 // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or 636 // ligatures are enabled. 637 GlyphBuffer localGlyphBuffer; 638 it.advance(runInfo.from, &localGlyphBuffer); 639 float beforeWidth = it.m_runWidthSoFar; 640 it.advance(runInfo.to, &glyphBuffer); 641 642 if (glyphBuffer.isEmpty()) 643 return 0; 644 645 float afterWidth = it.m_runWidthSoFar; 646 647 if (runInfo.run.rtl()) { 648 float finalRoundingWidth = it.m_finalRoundingWidth; 649 it.advance(runInfo.run.length(), &localGlyphBuffer); 650 initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth; 651 glyphBuffer.reverse(); 652 } else { 653 initialAdvance = beforeWidth; 654 } 655 656 return initialAdvance; 657 } 658 659 void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const 660 { 661 // This glyph buffer holds our glyphs+advances+font data for each glyph. 662 GlyphBuffer glyphBuffer; 663 664 float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer); 665 666 if (glyphBuffer.isEmpty()) 667 return; 668 669 FloatPoint startPoint(startX, point.y()); 670 drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint); 671 } 672 673 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const 674 { 675 GlyphBuffer glyphBuffer; 676 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer, ForTextEmphasis); 677 678 if (glyphBuffer.isEmpty()) 679 return; 680 681 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 682 } 683 684 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const 685 { 686 // Draw each contiguous run of glyphs that use the same font data. 687 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 688 FloatPoint startPoint(point); 689 FloatPoint nextPoint = startPoint + glyphBuffer.advanceAt(0); 690 unsigned lastFrom = 0; 691 unsigned nextGlyph = 1; 692 #if ENABLE(SVG_FONTS) 693 TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext(); 694 #endif 695 while (nextGlyph < glyphBuffer.size()) { 696 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); 697 698 if (nextFontData != fontData) { 699 #if ENABLE(SVG_FONTS) 700 if (renderingContext && fontData->isSVGFont()) 701 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 702 else 703 #endif 704 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds); 705 706 lastFrom = nextGlyph; 707 fontData = nextFontData; 708 startPoint = nextPoint; 709 } 710 nextPoint += glyphBuffer.advanceAt(nextGlyph); 711 nextGlyph++; 712 } 713 714 #if ENABLE(SVG_FONTS) 715 if (renderingContext && fontData->isSVGFont()) 716 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 717 else 718 #endif 719 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds); 720 } 721 722 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) 723 { 724 if (fontData->platformData().orientation() == Horizontal) { 725 FloatRect bounds = fontData->boundsForGlyph(glyph); 726 return bounds.x() + bounds.width() / 2; 727 } 728 // FIXME: Use glyph bounds once they make sense for vertical fonts. 729 return fontData->widthForGlyph(glyph) / 2; 730 } 731 732 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffer, size_t i) 733 { 734 return glyphBuffer.advanceAt(i).width() / 2; 735 } 736 737 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const 738 { 739 FontCachePurgePreventer purgePreventer; 740 741 GlyphData markGlyphData; 742 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 743 return; 744 745 const SimpleFontData* markFontData = markGlyphData.fontData; 746 ASSERT(markFontData); 747 if (!markFontData) 748 return; 749 750 Glyph markGlyph = markGlyphData.glyph; 751 Glyph spaceGlyph = markFontData->spaceGlyph(); 752 753 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0); 754 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y()); 755 756 GlyphBuffer markBuffer; 757 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) { 758 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1); 759 float advance = glyphBuffer.advanceAt(i).width() - middleOfLastGlyph + middleOfNextGlyph; 760 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance); 761 middleOfLastGlyph = middleOfNextGlyph; 762 } 763 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0); 764 765 drawGlyphBuffer(context, runInfo, markBuffer, startPoint); 766 } 767 768 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const 769 { 770 WidthIterator it(this, run, fallbackFonts, glyphBounds); 771 GlyphBuffer glyphBuffer; 772 it.advance(run.length(), (fontDescription().typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0); 773 774 if (glyphBounds) { 775 glyphBounds->setTop(floorf(-it.minGlyphBoundingBoxY())); 776 glyphBounds->setBottom(ceilf(it.maxGlyphBoundingBoxY())); 777 glyphBounds->setLeft(floorf(it.firstGlyphOverflow())); 778 glyphBounds->setRight(ceilf(it.lastGlyphOverflow())); 779 } 780 781 return it.m_runWidthSoFar; 782 } 783 784 FloatRect Font::pixelSnappedSelectionRect(float fromX, float toX, float y, float height) 785 { 786 // Using roundf() rather than ceilf() for the right edge as a compromise to 787 // ensure correct caret positioning. 788 // Use LayoutUnit::epsilon() to ensure that values that cannot be stored as 789 // an integer are floored to n and not n-1 due to floating point imprecision. 790 float pixelAlignedX = floorf(fromX + LayoutUnit::epsilon()); 791 return FloatRect(pixelAlignedX, y, roundf(toX) - pixelAlignedX, height); 792 } 793 794 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to, bool accountForGlyphBounds) const 795 { 796 GlyphBuffer glyphBuffer; 797 WidthIterator it(this, run, 0, accountForGlyphBounds); 798 it.advance(from, &glyphBuffer); 799 float fromX = it.m_runWidthSoFar; 800 it.advance(to, &glyphBuffer); 801 float toX = it.m_runWidthSoFar; 802 803 if (run.rtl()) { 804 it.advance(run.length(), &glyphBuffer); 805 float totalWidth = it.m_runWidthSoFar; 806 float beforeWidth = fromX; 807 float afterWidth = toX; 808 fromX = totalWidth - afterWidth; 809 toX = totalWidth - beforeWidth; 810 } 811 812 return pixelSnappedSelectionRect(point.x() + fromX, point.x() + toX, 813 accountForGlyphBounds ? it.minGlyphBoundingBoxY() : point.y(), 814 accountForGlyphBounds ? it.maxGlyphBoundingBoxY() - it.minGlyphBoundingBoxY() : h); 815 } 816 817 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const 818 { 819 float delta = x; 820 821 WidthIterator it(this, run); 822 GlyphBuffer localGlyphBuffer; 823 unsigned offset; 824 if (run.rtl()) { 825 delta -= floatWidthForSimpleText(run); 826 while (1) { 827 offset = it.m_currentCharacter; 828 float w; 829 if (!it.advanceOneCharacter(w, localGlyphBuffer)) 830 break; 831 delta += w; 832 if (includePartialGlyphs) { 833 if (delta - w / 2 >= 0) 834 break; 835 } else { 836 if (delta >= 0) 837 break; 838 } 839 } 840 } else { 841 while (1) { 842 offset = it.m_currentCharacter; 843 float w; 844 if (!it.advanceOneCharacter(w, localGlyphBuffer)) 845 break; 846 delta -= w; 847 if (includePartialGlyphs) { 848 if (delta + w / 2 <= 0) 849 break; 850 } else { 851 if (delta <= 0) 852 break; 853 } 854 } 855 } 856 857 return offset; 858 } 859 860 } 861