Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 #include "platform/fonts/WidthIterator.h" | 35 #include "platform/fonts/WidthIterator.h" |
| 36 #include "platform/geometry/FloatRect.h" | 36 #include "platform/geometry/FloatRect.h" |
| 37 #include "platform/text/TextRun.h" | 37 #include "platform/text/TextRun.h" |
| 38 #include "wtf/MainThread.h" | 38 #include "wtf/MainThread.h" |
| 39 #include "wtf/StdLibExtras.h" | 39 #include "wtf/StdLibExtras.h" |
| 40 #include "wtf/unicode/CharacterNames.h" | 40 #include "wtf/unicode/CharacterNames.h" |
| 41 #include "wtf/unicode/Unicode.h" | 41 #include "wtf/unicode/Unicode.h" |
| 42 | 42 |
| 43 using namespace WTF; | 43 using namespace WTF; |
| 44 using namespace Unicode; | 44 using namespace Unicode; |
| 45 using namespace std; | |
| 46 | 45 |
| 47 namespace blink { | 46 namespace blink { |
| 48 | 47 |
| 49 CodePath Font::s_codePath = AutoPath; | 48 CodePath Font::s_codePath = AutoPath; |
| 50 | 49 |
| 51 // ============================================================================= =============== | 50 // ============================================================================= =============== |
| 52 // Font Implementation (Cross-Platform Portion) | 51 // Font Implementation (Cross-Platform Portion) |
| 53 // ============================================================================= =============== | 52 // ============================================================================= =============== |
| 54 | 53 |
| 55 Font::Font() | 54 Font::Font() |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 133 |
| 135 if (codePathToUse != ComplexPath) | 134 if (codePathToUse != ComplexPath) |
| 136 drawEmphasisMarksForSimpleText(context, runInfo, mark, point); | 135 drawEmphasisMarksForSimpleText(context, runInfo, mark, point); |
| 137 else | 136 else |
| 138 drawEmphasisMarksForComplexText(context, runInfo, mark, point); | 137 drawEmphasisMarksForComplexText(context, runInfo, mark, point); |
| 139 } | 138 } |
| 140 | 139 |
| 141 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, | 140 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, |
| 142 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) | 141 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) |
| 143 { | 142 { |
| 144 glyphOverflow->top = max<int>(glyphOverflow->top, | 143 glyphOverflow->top = std::max<int>(glyphOverflow->top, |
| 145 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); | 144 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); |
| 146 glyphOverflow->bottom = max<int>(glyphOverflow->bottom, | 145 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, |
| 147 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); | 146 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); |
| 148 glyphOverflow->left = glyphBounds.left(); | 147 glyphOverflow->left = glyphBounds.left(); |
| 149 glyphOverflow->right = glyphBounds.right(); | 148 glyphOverflow->right = glyphBounds.right(); |
| 150 } | 149 } |
| 151 | 150 |
| 152 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo nts, GlyphOverflow* glyphOverflow) const | 151 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo nts, GlyphOverflow* glyphOverflow) const |
| 153 { | 152 { |
| 154 CodePath codePathToUse = codePath(run); | 153 CodePath codePathToUse = codePath(run); |
| 155 if (codePathToUse != ComplexPath) { | 154 if (codePathToUse != ComplexPath) { |
| 156 // The complex path is more restrictive about returning fallback fonts t han the simple path, so we need an explicit test to make their behaviors match. | 155 // The complex path is more restrictive about returning fallback fonts t han the simple path, so we need an explicit test to make their behaviors match. |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacte rWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, Gly phData& data, GlyphPage* page, unsigned pageNumber) | 362 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacte rWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, Gly phData& data, GlyphPage* page, unsigned pageNumber) |
| 364 { | 363 { |
| 365 if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(cha racter)) { | 364 if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(cha racter)) { |
| 366 RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientati onFontData(); | 365 RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientati onFontData(); |
| 367 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(upright FontData.get(), pageNumber); | 366 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(upright FontData.get(), pageNumber); |
| 368 GlyphPage* uprightPage = uprightNode->page(); | 367 GlyphPage* uprightPage = uprightNode->page(); |
| 369 if (uprightPage) { | 368 if (uprightPage) { |
| 370 GlyphData uprightData = uprightPage->glyphDataForCharacter(character ); | 369 GlyphData uprightData = uprightPage->glyphDataForCharacter(character ); |
| 371 // If the glyphs are the same, then we know we can just use the hori zontal glyph rotated vertically to be upright. | 370 // If the glyphs are the same, then we know we can just use the hori zontal glyph rotated vertically to be upright. |
| 372 if (data.glyph == uprightData.glyph) | 371 if (data.glyph == uprightData.glyph) |
| 373 return make_pair(data, page); | 372 return std::make_pair(data, page); |
|
jamesr
2014/08/28 19:57:21
given the number of make_pair calls i think adding
| |
| 374 // The glyphs are distinct, meaning that the font has a vertical-rig ht glyph baked into it. We can't use that | 373 // The glyphs are distinct, meaning that the font has a vertical-rig ht glyph baked into it. We can't use that |
| 375 // glyph, so we fall back to the upright data and use the horizontal glyph. | 374 // glyph, so we fall back to the upright data and use the horizontal glyph. |
| 376 if (uprightData.fontData) | 375 if (uprightData.fontData) |
| 377 return make_pair(uprightData, uprightPage); | 376 return std::make_pair(uprightData, uprightPage); |
| 378 } | 377 } |
| 379 } else if (orientation == NonCJKGlyphOrientationVerticalRight) { | 378 } else if (orientation == NonCJKGlyphOrientationVerticalRight) { |
| 380 RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRi ghtOrientationFontData(); | 379 RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRi ghtOrientationFontData(); |
| 381 GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(v erticalRightFontData.get(), pageNumber); | 380 GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(v erticalRightFontData.get(), pageNumber); |
| 382 GlyphPage* verticalRightPage = verticalRightNode->page(); | 381 GlyphPage* verticalRightPage = verticalRightNode->page(); |
| 383 if (verticalRightPage) { | 382 if (verticalRightPage) { |
| 384 GlyphData verticalRightData = verticalRightPage->glyphDataForCharact er(character); | 383 GlyphData verticalRightData = verticalRightPage->glyphDataForCharact er(character); |
| 385 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked | 384 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked |
| 386 // into it. | 385 // into it. |
| 387 if (data.glyph != verticalRightData.glyph) | 386 if (data.glyph != verticalRightData.glyph) |
| 388 return make_pair(data, page); | 387 return std::make_pair(data, page); |
| 389 // The glyphs are identical, meaning that we should just use the hor izontal glyph. | 388 // The glyphs are identical, meaning that we should just use the hor izontal glyph. |
| 390 if (verticalRightData.fontData) | 389 if (verticalRightData.fontData) |
| 391 return make_pair(verticalRightData, verticalRightPage); | 390 return std::make_pair(verticalRightData, verticalRightPage); |
| 392 } | 391 } |
| 393 } | 392 } |
| 394 return make_pair(data, page); | 393 return std::make_pair(data, page); |
| 395 } | 394 } |
| 396 | 395 |
| 397 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b ool mirror, FontDataVariant variant) const | 396 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b ool mirror, FontDataVariant variant) const |
| 398 { | 397 { |
| 399 ASSERT(isMainThread()); | 398 ASSERT(isMainThread()); |
| 400 | 399 |
| 401 if (variant == AutoVariant) { | 400 if (variant == AutoVariant) { |
| 402 if (m_fontDescription.variant() == FontVariantSmallCaps && !primaryFont( )->isSVGFont()) { | 401 if (m_fontDescription.variant() == FontVariantSmallCaps && !primaryFont( )->isSVGFont()) { |
| 403 UChar32 upperC = toUpper(c); | 402 UChar32 upperC = toUpper(c); |
| 404 if (upperC != c) { | 403 if (upperC != c) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 424 } | 423 } |
| 425 | 424 |
| 426 GlyphPage* page = 0; | 425 GlyphPage* page = 0; |
| 427 if (variant == NormalVariant) { | 426 if (variant == NormalVariant) { |
| 428 // Fastest loop, for the common case (normal variant). | 427 // Fastest loop, for the common case (normal variant). |
| 429 while (true) { | 428 while (true) { |
| 430 page = node->page(); | 429 page = node->page(); |
| 431 if (page) { | 430 if (page) { |
| 432 GlyphData data = page->glyphDataForCharacter(c); | 431 GlyphData data = page->glyphDataForCharacter(c); |
| 433 if (data.fontData && (data.fontData->platformData().orientation( ) == Horizontal || data.fontData->isTextOrientationFallback())) | 432 if (data.fontData && (data.fontData->platformData().orientation( ) == Horizontal || data.fontData->isTextOrientationFallback())) |
| 434 return make_pair(data, page); | 433 return std::make_pair(data, page); |
| 435 | 434 |
| 436 if (data.fontData) { | 435 if (data.fontData) { |
| 437 if (Character::isCJKIdeographOrSymbol(c)) { | 436 if (Character::isCJKIdeographOrSymbol(c)) { |
| 438 if (!data.fontData->hasVerticalGlyphs()) { | 437 if (!data.fontData->hasVerticalGlyphs()) { |
| 439 // Use the broken ideograph font data. The broken id eograph font will use the horizontal width of glyphs | 438 // Use the broken ideograph font data. The broken id eograph font will use the horizontal width of glyphs |
| 440 // to make sure you get a square (even for broken gl yphs like symbols used for punctuation). | 439 // to make sure you get a square (even for broken gl yphs like symbols used for punctuation). |
| 441 variant = BrokenIdeographVariant; | 440 variant = BrokenIdeographVariant; |
| 442 break; | 441 break; |
| 443 } | 442 } |
| 444 } else { | 443 } else { |
| 445 return glyphDataAndPageForNonCJKCharacterWithGlyphOrient ation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); | 444 return glyphDataAndPageForNonCJKCharacterWithGlyphOrient ation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); |
| 446 } | 445 } |
| 447 | 446 |
| 448 return make_pair(data, page); | 447 return std::make_pair(data, page); |
| 449 } | 448 } |
| 450 | 449 |
| 451 if (node->isSystemFallback()) | 450 if (node->isSystemFallback()) |
| 452 break; | 451 break; |
| 453 } | 452 } |
| 454 | 453 |
| 455 // Proceed with the fallback list. | 454 // Proceed with the fallback list. |
| 456 node = node->getChild(fontDataAt(node->level()), pageNumber); | 455 node = node->getChild(fontDataAt(node->level()), pageNumber); |
| 457 m_fontFallbackList->setPageNode(pageNumber, node); | 456 m_fontFallbackList->setPageNode(pageNumber, node); |
| 458 } | 457 } |
| 459 } | 458 } |
| 460 if (variant != NormalVariant) { | 459 if (variant != NormalVariant) { |
| 461 while (true) { | 460 while (true) { |
| 462 page = node->page(); | 461 page = node->page(); |
| 463 if (page) { | 462 if (page) { |
| 464 GlyphData data = page->glyphDataForCharacter(c); | 463 GlyphData data = page->glyphDataForCharacter(c); |
| 465 if (data.fontData) { | 464 if (data.fontData) { |
| 466 // The variantFontData function should not normally return 0 . | 465 // The variantFontData function should not normally return 0 . |
| 467 // But if it does, we will just render the capital letter bi g. | 466 // But if it does, we will just render the capital letter bi g. |
| 468 RefPtr<SimpleFontData> variantFontData = data.fontData->vari antFontData(m_fontDescription, variant); | 467 RefPtr<SimpleFontData> variantFontData = data.fontData->vari antFontData(m_fontDescription, variant); |
| 469 if (!variantFontData) | 468 if (!variantFontData) |
| 470 return make_pair(data, page); | 469 return std::make_pair(data, page); |
| 471 | 470 |
| 472 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootC hild(variantFontData.get(), pageNumber); | 471 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootC hild(variantFontData.get(), pageNumber); |
| 473 GlyphPage* variantPage = variantNode->page(); | 472 GlyphPage* variantPage = variantNode->page(); |
| 474 if (variantPage) { | 473 if (variantPage) { |
| 475 GlyphData data = variantPage->glyphDataForCharacter(c); | 474 GlyphData data = variantPage->glyphDataForCharacter(c); |
| 476 if (data.fontData) | 475 if (data.fontData) |
| 477 return make_pair(data, variantPage); | 476 return std::make_pair(data, variantPage); |
| 478 } | 477 } |
| 479 | 478 |
| 480 // Do not attempt system fallback off the variantFontData. T his is the very unlikely case that | 479 // Do not attempt system fallback off the variantFontData. T his is the very unlikely case that |
| 481 // a font has the lowercase character but the small caps fon t does not have its uppercase version. | 480 // a font has the lowercase character but the small caps fon t does not have its uppercase version. |
| 482 return make_pair(variantFontData->missingGlyphData(), page); | 481 return std::make_pair(variantFontData->missingGlyphData(), p age); |
| 483 } | 482 } |
| 484 | 483 |
| 485 if (node->isSystemFallback()) | 484 if (node->isSystemFallback()) |
| 486 break; | 485 break; |
| 487 } | 486 } |
| 488 | 487 |
| 489 // Proceed with the fallback list. | 488 // Proceed with the fallback list. |
| 490 node = node->getChild(fontDataAt(node->level()), pageNumber); | 489 node = node->getChild(fontDataAt(node->level()), pageNumber); |
| 491 m_fontFallbackList->setPageNode(pageNumber, node); | 490 m_fontFallbackList->setPageNode(pageNumber, node); |
| 492 } | 491 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 512 if (variant != NormalVariant) | 511 if (variant != NormalVariant) |
| 513 characterFontData = characterFontData->variantFontData(m_fontDescrip tion, variant); | 512 characterFontData = characterFontData->variantFontData(m_fontDescrip tion, variant); |
| 514 } | 513 } |
| 515 if (characterFontData) { | 514 if (characterFontData) { |
| 516 // Got the fallback glyph and font. | 515 // Got the fallback glyph and font. |
| 517 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontD ata.get(), pageNumber)->page(); | 516 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontD ata.get(), pageNumber)->page(); |
| 518 GlyphData data = fallbackPage && fallbackPage->glyphForCharacter(c) ? fa llbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); | 517 GlyphData data = fallbackPage && fallbackPage->glyphForCharacter(c) ? fa llbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); |
| 519 // Cache it so we don't have to do system fallback again next time. | 518 // Cache it so we don't have to do system fallback again next time. |
| 520 if (variant == NormalVariant) { | 519 if (variant == NormalVariant) { |
| 521 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); | 520 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); |
| 522 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphP ageTreeLevel(), node->level())); | 521 data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxG lyphPageTreeLevel(), node->level())); |
| 523 if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platform Data().orientation() != Horizontal && !data.fontData->isTextOrientationFallback( )) | 522 if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platform Data().orientation() != Horizontal && !data.fontData->isTextOrientationFallback( )) |
| 524 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); | 523 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber); |
| 525 } | 524 } |
| 526 return make_pair(data, page); | 525 return std::make_pair(data, page); |
| 527 } | 526 } |
| 528 | 527 |
| 529 // Even system fallback can fail; use the missing glyph in that case. | 528 // Even system fallback can fail; use the missing glyph in that case. |
| 530 // FIXME: It would be nicer to use the missing glyph from the last resort fo nt instead. | 529 // FIXME: It would be nicer to use the missing glyph from the last resort fo nt instead. |
| 531 GlyphData data = primaryFont()->missingGlyphData(); | 530 GlyphData data = primaryFont()->missingGlyphData(); |
| 532 if (variant == NormalVariant) { | 531 if (variant == NormalVariant) { |
| 533 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); | 532 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); |
| 534 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageT reeLevel(), node->level())); | 533 data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyph PageTreeLevel(), node->level())); |
| 535 } | 534 } |
| 536 return make_pair(data, page); | 535 return std::make_pair(data, page); |
| 537 } | 536 } |
| 538 | 537 |
| 539 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const | 538 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const |
| 540 { | 539 { |
| 541 unsigned pageNumber = (character / GlyphPage::size); | 540 unsigned pageNumber = (character / GlyphPage::size); |
| 542 | 541 |
| 543 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pag eNumber); | 542 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pag eNumber); |
| 544 GlyphPage* page = node->page(); | 543 GlyphPage* page = node->page(); |
| 545 | 544 |
| 546 return page && page->glyphForCharacter(character); | 545 return page && page->glyphForCharacter(character); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 836 if (delta <= 0) | 835 if (delta <= 0) |
| 837 break; | 836 break; |
| 838 } | 837 } |
| 839 } | 838 } |
| 840 } | 839 } |
| 841 | 840 |
| 842 return offset; | 841 return offset; |
| 843 } | 842 } |
| 844 | 843 |
| 845 } // namespace blink | 844 } // namespace blink |
| OLD | NEW |