| 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 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "platform/fonts/Font.h" | 25 #include "platform/fonts/Font.h" |
| 26 | 26 |
| 27 #include "platform/LayoutTestSupport.h" | 27 #include "platform/LayoutTestSupport.h" |
| 28 #include "platform/LayoutUnit.h" | 28 #include "platform/LayoutUnit.h" |
| 29 #include "platform/RuntimeEnabledFeatures.h" | 29 #include "platform/RuntimeEnabledFeatures.h" |
| 30 #include "platform/fonts/CharacterRange.h" | 30 #include "platform/fonts/CharacterRange.h" |
| 31 #include "platform/fonts/FontCache.h" | 31 #include "platform/fonts/FontCache.h" |
| 32 #include "platform/fonts/FontFallbackIterator.h" | 32 #include "platform/fonts/FontFallbackIterator.h" |
| 33 #include "platform/fonts/FontFallbackList.h" | 33 #include "platform/fonts/FontFallbackList.h" |
| 34 #include "platform/fonts/GlyphBuffer.h" | 34 #include "platform/fonts/GlyphBuffer.h" |
| 35 #include "platform/fonts/GlyphPageTreeNode.h" | |
| 36 #include "platform/fonts/SimpleFontData.h" | 35 #include "platform/fonts/SimpleFontData.h" |
| 37 #include "platform/fonts/shaping/CachingWordShaper.h" | 36 #include "platform/fonts/shaping/CachingWordShaper.h" |
| 38 #include "platform/fonts/shaping/SimpleShaper.h" | |
| 39 #include "platform/geometry/FloatRect.h" | 37 #include "platform/geometry/FloatRect.h" |
| 40 #include "platform/text/BidiResolver.h" | 38 #include "platform/text/BidiResolver.h" |
| 41 #include "platform/text/Character.h" | 39 #include "platform/text/Character.h" |
| 42 #include "platform/text/TextRun.h" | 40 #include "platform/text/TextRun.h" |
| 43 #include "platform/text/TextRunIterator.h" | 41 #include "platform/text/TextRunIterator.h" |
| 44 #include "platform/transforms/AffineTransform.h" | 42 #include "platform/transforms/AffineTransform.h" |
| 45 #include "third_party/skia/include/core/SkCanvas.h" | 43 #include "third_party/skia/include/core/SkCanvas.h" |
| 46 #include "third_party/skia/include/core/SkPaint.h" | 44 #include "third_party/skia/include/core/SkPaint.h" |
| 47 #include "third_party/skia/include/core/SkTextBlob.h" | 45 #include "third_party/skia/include/core/SkTextBlob.h" |
| 48 #include "wtf/StdLibExtras.h" | 46 #include "wtf/StdLibExtras.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // in trouble). Still, this is pretty disgusting, and could eventually be | 101 // in trouble). Still, this is pretty disgusting, and could eventually be |
| 104 // rectified by using RefPtrs for Fonts themselves. | 102 // rectified by using RefPtrs for Fonts themselves. |
| 105 if (!m_fontFallbackList) | 103 if (!m_fontFallbackList) |
| 106 m_fontFallbackList = FontFallbackList::create(); | 104 m_fontFallbackList = FontFallbackList::create(); |
| 107 m_fontFallbackList->invalidate(fontSelector); | 105 m_fontFallbackList->invalidate(fontSelector); |
| 108 } | 106 } |
| 109 | 107 |
| 110 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, | 108 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, |
| 111 GlyphBuffer& glyphBuffer, | 109 GlyphBuffer& glyphBuffer, |
| 112 const GlyphData* emphasisData) const { | 110 const GlyphData* emphasisData) const { |
| 113 if (codePath(runInfo) == ComplexPath) { | 111 float width; |
| 114 float width; | 112 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); |
| 115 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); | 113 if (emphasisData) { |
| 116 if (emphasisData) { | 114 width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run, |
| 117 width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run, | 115 emphasisData, &glyphBuffer, |
| 118 emphasisData, &glyphBuffer, | 116 runInfo.from, runInfo.to); |
| 119 runInfo.from, runInfo.to); | 117 } else { |
| 120 } else { | 118 width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, &glyphBuffer, |
| 121 width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, &glyphBuffer, | 119 runInfo.from, runInfo.to); |
| 122 runInfo.from, runInfo.to); | |
| 123 } | |
| 124 | |
| 125 return width; | |
| 126 } | 120 } |
| 127 | |
| 128 SimpleShaper shaper(this, runInfo.run, emphasisData, | |
| 129 nullptr /* fallbackFonts */, nullptr); | |
| 130 shaper.advance(runInfo.from); | |
| 131 shaper.advance(runInfo.to, &glyphBuffer); | |
| 132 float width = shaper.runWidthSoFar(); | |
| 133 | |
| 134 if (runInfo.run.rtl()) { | |
| 135 // Glyphs are shaped & stored in RTL advance order - reverse them for LTR | |
| 136 // drawing. | |
| 137 shaper.advance(runInfo.run.length()); | |
| 138 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar()); | |
| 139 } | |
| 140 | |
| 141 return width; | 121 return width; |
| 142 } | 122 } |
| 143 | 123 |
| 144 bool Font::drawText(SkCanvas* canvas, | 124 bool Font::drawText(SkCanvas* canvas, |
| 145 const TextRunPaintInfo& runInfo, | 125 const TextRunPaintInfo& runInfo, |
| 146 const FloatPoint& point, | 126 const FloatPoint& point, |
| 147 float deviceScaleFactor, | 127 float deviceScaleFactor, |
| 148 const SkPaint& paint) const { | 128 const SkPaint& paint) const { |
| 149 // Don't draw anything while we are using custom fonts that are in the process | 129 // Don't draw anything while we are using custom fonts that are in the process |
| 150 // of loading. | 130 // of loading. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 | 228 |
| 249 drawGlyphBuffer(canvas, paint, runInfo, glyphBuffer, point, | 229 drawGlyphBuffer(canvas, paint, runInfo, glyphBuffer, point, |
| 250 deviceScaleFactor); | 230 deviceScaleFactor); |
| 251 } | 231 } |
| 252 | 232 |
| 253 float Font::width(const TextRun& run, | 233 float Font::width(const TextRun& run, |
| 254 HashSet<const SimpleFontData*>* fallbackFonts, | 234 HashSet<const SimpleFontData*>* fallbackFonts, |
| 255 FloatRect* glyphBounds) const { | 235 FloatRect* glyphBounds) const { |
| 256 FontCachePurgePreventer purgePreventer; | 236 FontCachePurgePreventer purgePreventer; |
| 257 | 237 |
| 258 if (codePath(TextRunPaintInfo(run)) == ComplexPath) | 238 return floatWidthForComplexText(run, fallbackFonts, glyphBounds); |
| 259 return floatWidthForComplexText(run, fallbackFonts, glyphBounds); | |
| 260 return floatWidthForSimpleText(run, fallbackFonts, glyphBounds); | |
| 261 } | 239 } |
| 262 | 240 |
| 263 namespace { | 241 namespace { |
| 264 | 242 |
| 265 enum BlobRotation { | 243 enum BlobRotation { |
| 266 NoRotation, | 244 NoRotation, |
| 267 CCWRotation, | 245 CCWRotation, |
| 268 }; | 246 }; |
| 269 | 247 |
| 270 class GlyphBufferBloberizer { | 248 class GlyphBufferBloberizer { |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 int to, | 470 int to, |
| 493 bool accountForGlyphBounds) const { | 471 bool accountForGlyphBounds) const { |
| 494 to = (to == -1 ? run.length() : to); | 472 to = (to == -1 ? run.length() : to); |
| 495 | 473 |
| 496 TextRunPaintInfo runInfo(run); | 474 TextRunPaintInfo runInfo(run); |
| 497 runInfo.from = from; | 475 runInfo.from = from; |
| 498 runInfo.to = to; | 476 runInfo.to = to; |
| 499 | 477 |
| 500 FontCachePurgePreventer purgePreventer; | 478 FontCachePurgePreventer purgePreventer; |
| 501 | 479 |
| 502 if (codePath(runInfo) != ComplexPath) | |
| 503 return pixelSnappedSelectionRect(selectionRectForSimpleText( | |
| 504 run, point, h, from, to, accountForGlyphBounds)); | |
| 505 return pixelSnappedSelectionRect( | 480 return pixelSnappedSelectionRect( |
| 506 selectionRectForComplexText(run, point, h, from, to)); | 481 selectionRectForComplexText(run, point, h, from, to)); |
| 507 } | 482 } |
| 508 | 483 |
| 509 int Font::offsetForPosition(const TextRun& run, | 484 int Font::offsetForPosition(const TextRun& run, |
| 510 float x, | 485 float x, |
| 511 bool includePartialGlyphs) const { | 486 bool includePartialGlyphs) const { |
| 512 FontCachePurgePreventer purgePreventer; | 487 FontCachePurgePreventer purgePreventer; |
| 513 | |
| 514 if (codePath(TextRunPaintInfo(run)) != ComplexPath && | |
| 515 !getFontDescription().getTypesettingFeatures()) | |
| 516 return offsetForPositionForSimpleText(run, x, includePartialGlyphs); | |
| 517 | |
| 518 return offsetForPositionForComplexText(run, x, includePartialGlyphs); | 488 return offsetForPositionForComplexText(run, x, includePartialGlyphs); |
| 519 } | 489 } |
| 520 | 490 |
| 521 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const { | |
| 522 if (RuntimeEnabledFeatures::alwaysUseComplexTextEnabled() || | |
| 523 LayoutTestSupport::alwaysUseComplexTextForTest()) { | |
| 524 return ComplexPath; | |
| 525 } | |
| 526 | |
| 527 const TextRun& run = runInfo.run; | |
| 528 | |
| 529 if (getFontDescription().getTypesettingFeatures()) | |
| 530 return ComplexPath; | |
| 531 | |
| 532 if (m_fontDescription.featureSettings() && | |
| 533 m_fontDescription.featureSettings()->size() > 0) | |
| 534 return ComplexPath; | |
| 535 | |
| 536 if (m_fontDescription.isVerticalBaseline()) | |
| 537 return ComplexPath; | |
| 538 | |
| 539 if (m_fontDescription.widthVariant() != RegularWidth) | |
| 540 return ComplexPath; | |
| 541 | |
| 542 // FIXME: This really shouldn't be needed but for some reason the | |
| 543 // TextRendering setting doesn't propagate to typesettingFeatures in time | |
| 544 // for the prefs width calculation. | |
| 545 if (getFontDescription().textRendering() == OptimizeLegibility || | |
| 546 getFontDescription().textRendering() == GeometricPrecision) | |
| 547 return ComplexPath; | |
| 548 | |
| 549 if (run.is8Bit()) | |
| 550 return SimplePath; | |
| 551 | |
| 552 // Start from 0 since drawing and highlighting also measure the characters | |
| 553 // before run->from. | |
| 554 return Character::characterRangeCodePath(run.characters16(), run.length()); | |
| 555 } | |
| 556 | |
| 557 bool Font::canShapeWordByWord() const { | 491 bool Font::canShapeWordByWord() const { |
| 558 if (!m_shapeWordByWordComputed) { | 492 if (!m_shapeWordByWordComputed) { |
| 559 m_canShapeWordByWord = computeCanShapeWordByWord(); | 493 m_canShapeWordByWord = computeCanShapeWordByWord(); |
| 560 m_shapeWordByWordComputed = true; | 494 m_shapeWordByWordComputed = true; |
| 561 } | 495 } |
| 562 return m_canShapeWordByWord; | 496 return m_canShapeWordByWord; |
| 563 }; | 497 }; |
| 564 | 498 |
| 565 bool Font::computeCanShapeWordByWord() const { | 499 bool Font::computeCanShapeWordByWord() const { |
| 566 if (!getFontDescription().getTypesettingFeatures()) | 500 if (!getFontDescription().getTypesettingFeatures()) |
| 567 return true; | 501 return true; |
| 568 | 502 |
| 569 if (!primaryFont()) | 503 if (!primaryFont()) |
| 570 return false; | 504 return false; |
| 571 | 505 |
| 572 const FontPlatformData& platformData = primaryFont()->platformData(); | 506 const FontPlatformData& platformData = primaryFont()->platformData(); |
| 573 TypesettingFeatures features = getFontDescription().getTypesettingFeatures(); | 507 TypesettingFeatures features = getFontDescription().getTypesettingFeatures(); |
| 574 return !platformData.hasSpaceInLigaturesOrKerning(features); | 508 return !platformData.hasSpaceInLigaturesOrKerning(features); |
| 575 }; | 509 }; |
| 576 | 510 |
| 577 void Font::willUseFontData(const String& text) const { | 511 void Font::willUseFontData(const String& text) const { |
| 578 const FontFamily& family = getFontDescription().family(); | 512 const FontFamily& family = getFontDescription().family(); |
| 579 if (m_fontFallbackList && m_fontFallbackList->getFontSelector() && | 513 if (m_fontFallbackList && m_fontFallbackList->getFontSelector() && |
| 580 !family.familyIsEmpty()) | 514 !family.familyIsEmpty()) |
| 581 m_fontFallbackList->getFontSelector()->willUseFontData( | 515 m_fontFallbackList->getFontSelector()->willUseFontData( |
| 582 getFontDescription(), family.family(), text); | 516 getFontDescription(), family.family(), text); |
| 583 } | 517 } |
| 584 | 518 |
| 585 static inline GlyphData glyphDataForNonCJKCharacterWithGlyphOrientation( | |
| 586 UChar32 character, | |
| 587 bool isUpright, | |
| 588 GlyphData& data, | |
| 589 unsigned pageNumber) { | |
| 590 if (isUpright) { | |
| 591 RefPtr<SimpleFontData> uprightFontData = | |
| 592 data.fontData->uprightOrientationFontData(); | |
| 593 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getNormalRootChild( | |
| 594 uprightFontData.get(), pageNumber); | |
| 595 GlyphPage* uprightPage = uprightNode->page(); | |
| 596 if (uprightPage) { | |
| 597 GlyphData uprightData = uprightPage->glyphDataForCharacter(character); | |
| 598 // If the glyphs are the same, then we know we can just use the horizontal | |
| 599 // glyph rotated vertically to be upright. | |
| 600 if (data.glyph == uprightData.glyph) | |
| 601 return data; | |
| 602 // The glyphs are distinct, meaning that the font has a vertical-right | |
| 603 // glyph baked into it. We can't use that glyph, so we fall back to the | |
| 604 // upright data and use the horizontal glyph. | |
| 605 if (uprightData.fontData) | |
| 606 return uprightData; | |
| 607 } | |
| 608 } else { | |
| 609 RefPtr<SimpleFontData> verticalRightFontData = | |
| 610 data.fontData->verticalRightOrientationFontData(); | |
| 611 GlyphPageTreeNode* verticalRightNode = | |
| 612 GlyphPageTreeNode::getNormalRootChild(verticalRightFontData.get(), | |
| 613 pageNumber); | |
| 614 GlyphPage* verticalRightPage = verticalRightNode->page(); | |
| 615 if (verticalRightPage) { | |
| 616 GlyphData verticalRightData = | |
| 617 verticalRightPage->glyphDataForCharacter(character); | |
| 618 // If the glyphs are distinct, we will make the assumption that the font | |
| 619 // has a vertical-right glyph baked into it. | |
| 620 if (data.glyph != verticalRightData.glyph) | |
| 621 return data; | |
| 622 // The glyphs are identical, meaning that we should just use the | |
| 623 // horizontal glyph. | |
| 624 if (verticalRightData.fontData) | |
| 625 return verticalRightData; | |
| 626 } | |
| 627 } | |
| 628 return data; | |
| 629 } | |
| 630 | |
| 631 PassRefPtr<FontFallbackIterator> Font::createFontFallbackIterator( | 519 PassRefPtr<FontFallbackIterator> Font::createFontFallbackIterator( |
| 632 FontFallbackPriority fallbackPriority) const { | 520 FontFallbackPriority fallbackPriority) const { |
| 633 return FontFallbackIterator::create(m_fontDescription, m_fontFallbackList, | 521 return FontFallbackIterator::create(m_fontDescription, m_fontFallbackList, |
| 634 fallbackPriority); | 522 fallbackPriority); |
| 635 } | 523 } |
| 636 | 524 |
| 637 GlyphData Font::glyphDataForCharacter(UChar32& c, | |
| 638 bool mirror, | |
| 639 bool normalizeSpace, | |
| 640 FontDataVariant variant) const { | |
| 641 ASSERT(isMainThread()); | |
| 642 | |
| 643 if (variant == AutoVariant) { | |
| 644 if (m_fontDescription.variantCaps() == FontDescription::SmallCaps) { | |
| 645 UChar32 upperC = | |
| 646 toUpper(c, LayoutLocale::localeString(m_fontDescription.locale())); | |
| 647 if (upperC != c) { | |
| 648 c = upperC; | |
| 649 variant = SmallCapsVariant; | |
| 650 } else { | |
| 651 variant = NormalVariant; | |
| 652 } | |
| 653 } else { | |
| 654 variant = NormalVariant; | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 if (normalizeSpace && Character::isNormalizedCanvasSpaceCharacter(c)) | |
| 659 c = spaceCharacter; | |
| 660 | |
| 661 if (mirror) | |
| 662 c = mirroredChar(c); | |
| 663 | |
| 664 unsigned pageNumber = (c / GlyphPage::size); | |
| 665 | |
| 666 GlyphPageTreeNodeBase* node = m_fontFallbackList->getPageNode(pageNumber); | |
| 667 if (!node) { | |
| 668 node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); | |
| 669 m_fontFallbackList->setPageNode(pageNumber, node); | |
| 670 } | |
| 671 RELEASE_ASSERT(node); // Diagnosing crbug.com/446566 crash bug. | |
| 672 | |
| 673 GlyphPage* page = 0; | |
| 674 if (variant == NormalVariant) { | |
| 675 // Fastest loop, for the common case (normal variant). | |
| 676 while (true) { | |
| 677 page = node->page(m_fontDescription.script()); | |
| 678 if (page) { | |
| 679 GlyphData data = page->glyphDataForCharacter(c); | |
| 680 if (data.fontData) { | |
| 681 if (!data.fontData->platformData().isVerticalAnyUpright() || | |
| 682 data.fontData->isTextOrientationFallback()) | |
| 683 return data; | |
| 684 | |
| 685 bool isUpright = m_fontDescription.isVerticalUpright(c); | |
| 686 if (!isUpright || !Character::isCJKIdeographOrSymbol(c)) | |
| 687 return glyphDataForNonCJKCharacterWithGlyphOrientation( | |
| 688 c, isUpright, data, pageNumber); | |
| 689 | |
| 690 return data; | |
| 691 } | |
| 692 | |
| 693 if (node->isSystemFallback()) | |
| 694 break; | |
| 695 } | |
| 696 | |
| 697 // Proceed with the fallback list. | |
| 698 node = toGlyphPageTreeNode(node)->getChild(fontDataAt(node->level()), | |
| 699 pageNumber); | |
| 700 m_fontFallbackList->setPageNode(pageNumber, node); | |
| 701 } | |
| 702 } | |
| 703 if (variant != NormalVariant) { | |
| 704 while (true) { | |
| 705 page = node->page(m_fontDescription.script()); | |
| 706 if (page) { | |
| 707 GlyphData data = page->glyphDataForCharacter(c); | |
| 708 if (data.fontData) { | |
| 709 // The variantFontData function should not normally return 0. | |
| 710 // But if it does, we will just render the capital letter big. | |
| 711 RefPtr<SimpleFontData> variantFontData = | |
| 712 data.fontData->variantFontData(m_fontDescription, variant); | |
| 713 if (!variantFontData) | |
| 714 return data; | |
| 715 | |
| 716 GlyphPageTreeNode* variantNode = | |
| 717 GlyphPageTreeNode::getNormalRootChild(variantFontData.get(), | |
| 718 pageNumber); | |
| 719 GlyphPage* variantPage = variantNode->page(); | |
| 720 if (variantPage) { | |
| 721 GlyphData data = variantPage->glyphDataForCharacter(c); | |
| 722 if (data.fontData) | |
| 723 return data; | |
| 724 } | |
| 725 | |
| 726 // Do not attempt system fallback off the variantFontData. This is the | |
| 727 // very unlikely case that a font has the lowercase character but the | |
| 728 // small caps font does not have its uppercase version. | |
| 729 return variantFontData->missingGlyphData(); | |
| 730 } | |
| 731 | |
| 732 if (node->isSystemFallback()) | |
| 733 break; | |
| 734 } | |
| 735 | |
| 736 // Proceed with the fallback list. | |
| 737 node = toGlyphPageTreeNode(node)->getChild(fontDataAt(node->level()), | |
| 738 pageNumber); | |
| 739 m_fontFallbackList->setPageNode(pageNumber, node); | |
| 740 } | |
| 741 } | |
| 742 | |
| 743 ASSERT(page); | |
| 744 ASSERT(node->isSystemFallback()); | |
| 745 | |
| 746 // System fallback is character-dependent. When we get here, we | |
| 747 // know that the character in question isn't in the system fallback | |
| 748 // font's glyph page. Try to lazily create it here. | |
| 749 | |
| 750 // FIXME: Unclear if this should normalizeSpaces above 0xFFFF. | |
| 751 // Doing so changes fast/text/international/plane2-diffs.html | |
| 752 UChar32 characterToRender = c; | |
| 753 if (characterToRender <= 0xFFFF) | |
| 754 characterToRender = Character::normalizeSpaces(characterToRender); | |
| 755 | |
| 756 const FontData* fontData = fontDataAt(0); | |
| 757 if (fontData) { | |
| 758 const SimpleFontData* fontDataToSubstitute = | |
| 759 fontData->fontDataForCharacter(characterToRender); | |
| 760 RefPtr<SimpleFontData> characterFontData = | |
| 761 FontCache::fontCache()->fallbackFontForCharacter( | |
| 762 m_fontDescription, characterToRender, fontDataToSubstitute); | |
| 763 if (characterFontData && variant != NormalVariant) { | |
| 764 characterFontData = | |
| 765 characterFontData->variantFontData(m_fontDescription, variant); | |
| 766 } | |
| 767 if (characterFontData) { | |
| 768 // Got the fallback glyph and font. | |
| 769 unsigned pageNumberForRendering = characterToRender / GlyphPage::size; | |
| 770 GlyphPage* fallbackPage = | |
| 771 GlyphPageTreeNode::getRootChild(characterFontData.get(), | |
| 772 pageNumberForRendering) | |
| 773 ->page(); | |
| 774 GlyphData data = | |
| 775 fallbackPage && fallbackPage->glyphForCharacter(characterToRender) | |
| 776 ? fallbackPage->glyphDataForCharacter(characterToRender) | |
| 777 : characterFontData->missingGlyphData(); | |
| 778 // Cache it so we don't have to do system fallback again next time. | |
| 779 if (variant == NormalVariant) { | |
| 780 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); | |
| 781 data.fontData->setMaxGlyphPageTreeLevel( | |
| 782 std::max(data.fontData->maxGlyphPageTreeLevel(), node->level())); | |
| 783 if (data.fontData->platformData().isVerticalAnyUpright() && | |
| 784 !data.fontData->isTextOrientationFallback() && | |
| 785 !Character::isCJKIdeographOrSymbol(characterToRender)) | |
| 786 return glyphDataForNonCJKCharacterWithGlyphOrientation( | |
| 787 characterToRender, | |
| 788 m_fontDescription.isVerticalUpright(characterToRender), data, | |
| 789 pageNumberForRendering); | |
| 790 } | |
| 791 return data; | |
| 792 } | |
| 793 } | |
| 794 | |
| 795 // Even system fallback can fail; use the missing glyph in that case. | |
| 796 // FIXME: It would be nicer to use the missing glyph from the last resort font | |
| 797 // instead. | |
| 798 DCHECK(primaryFont()); | |
| 799 if (!primaryFont()) | |
| 800 return GlyphData(); | |
| 801 GlyphData data = primaryFont()->missingGlyphData(); | |
| 802 if (variant == NormalVariant) { | |
| 803 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); | |
| 804 data.fontData->setMaxGlyphPageTreeLevel( | |
| 805 std::max(data.fontData->maxGlyphPageTreeLevel(), node->level())); | |
| 806 } | |
| 807 return data; | |
| 808 } | |
| 809 | |
| 810 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, | 525 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, |
| 811 GlyphData& glyphData) const { | 526 GlyphData& glyphData) const { |
| 812 if (mark.isEmpty()) | 527 if (mark.isEmpty()) |
| 813 return false; | 528 return false; |
| 814 | 529 |
| 815 TextRun emphasisMarkRun(mark, mark.length()); | 530 TextRun emphasisMarkRun(mark, mark.length()); |
| 816 TextRunPaintInfo emphasisPaintInfo(emphasisMarkRun); | 531 TextRunPaintInfo emphasisPaintInfo(emphasisMarkRun); |
| 817 GlyphBuffer glyphBuffer; | 532 GlyphBuffer glyphBuffer; |
| 818 buildGlyphBuffer(emphasisPaintInfo, glyphBuffer); | 533 buildGlyphBuffer(emphasisPaintInfo, glyphBuffer); |
| 819 | 534 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); | 636 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); |
| 922 auto ranges = shaper.individualCharacterRanges(this, run); | 637 auto ranges = shaper.individualCharacterRanges(this, run); |
| 923 // The shaper should return ranges.size == run.length but on some platforms | 638 // The shaper should return ranges.size == run.length but on some platforms |
| 924 // (OSX10.9.5) we are seeing cases in the upper end of the unicode range | 639 // (OSX10.9.5) we are seeing cases in the upper end of the unicode range |
| 925 // where this is not true (see: crbug.com/620952). To catch these cases on | 640 // where this is not true (see: crbug.com/620952). To catch these cases on |
| 926 // more popular platforms, and to protect users, we are using a CHECK here. | 641 // more popular platforms, and to protect users, we are using a CHECK here. |
| 927 CHECK_EQ(ranges.size(), run.length()); | 642 CHECK_EQ(ranges.size(), run.length()); |
| 928 return ranges; | 643 return ranges; |
| 929 } | 644 } |
| 930 | 645 |
| 931 float Font::floatWidthForSimpleText( | |
| 932 const TextRun& run, | |
| 933 HashSet<const SimpleFontData*>* fallbackFonts, | |
| 934 FloatRect* glyphBounds) const { | |
| 935 SimpleShaper shaper(this, run, nullptr, fallbackFonts, glyphBounds); | |
| 936 shaper.advance(run.length()); | |
| 937 return shaper.runWidthSoFar(); | |
| 938 } | |
| 939 | |
| 940 FloatRect Font::selectionRectForSimpleText(const TextRun& run, | |
| 941 const FloatPoint& point, | |
| 942 int h, | |
| 943 int from, | |
| 944 int to, | |
| 945 bool accountForGlyphBounds) const { | |
| 946 FloatRect bounds; | |
| 947 SimpleShaper shaper(this, run, nullptr, nullptr, | |
| 948 accountForGlyphBounds ? &bounds : nullptr); | |
| 949 shaper.advance(from); | |
| 950 float fromX = shaper.runWidthSoFar(); | |
| 951 shaper.advance(to); | |
| 952 float toX = shaper.runWidthSoFar(); | |
| 953 | |
| 954 if (run.rtl()) { | |
| 955 shaper.advance(run.length()); | |
| 956 float totalWidth = shaper.runWidthSoFar(); | |
| 957 float beforeWidth = fromX; | |
| 958 float afterWidth = toX; | |
| 959 fromX = totalWidth - afterWidth; | |
| 960 toX = totalWidth - beforeWidth; | |
| 961 } | |
| 962 | |
| 963 return FloatRect(point.x() + fromX, | |
| 964 accountForGlyphBounds ? bounds.y() : point.y(), toX - fromX, | |
| 965 accountForGlyphBounds ? bounds.maxY() - bounds.y() : h); | |
| 966 } | |
| 967 | |
| 968 int Font::offsetForPositionForSimpleText(const TextRun& run, | |
| 969 float x, | |
| 970 bool includePartialGlyphs) const { | |
| 971 float delta = x; | |
| 972 | |
| 973 SimpleShaper shaper(this, run); | |
| 974 unsigned offset; | |
| 975 if (run.rtl()) { | |
| 976 delta -= floatWidthForSimpleText(run); | |
| 977 while (1) { | |
| 978 offset = shaper.currentOffset(); | |
| 979 float w; | |
| 980 if (!shaper.advanceOneCharacter(w)) | |
| 981 break; | |
| 982 delta += w; | |
| 983 if (includePartialGlyphs) { | |
| 984 if (delta - w / 2 >= 0) | |
| 985 break; | |
| 986 } else { | |
| 987 if (delta >= 0) | |
| 988 break; | |
| 989 } | |
| 990 } | |
| 991 } else { | |
| 992 while (1) { | |
| 993 offset = shaper.currentOffset(); | |
| 994 float w; | |
| 995 if (!shaper.advanceOneCharacter(w)) | |
| 996 break; | |
| 997 delta -= w; | |
| 998 if (includePartialGlyphs) { | |
| 999 if (delta + w / 2 <= 0) | |
| 1000 break; | |
| 1001 } else { | |
| 1002 if (delta <= 0) | |
| 1003 break; | |
| 1004 } | |
| 1005 } | |
| 1006 } | |
| 1007 | |
| 1008 return offset; | |
| 1009 } | |
| 1010 | |
| 1011 bool Font::loadingCustomFonts() const { | 646 bool Font::loadingCustomFonts() const { |
| 1012 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 647 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
| 1013 } | 648 } |
| 1014 | 649 |
| 1015 bool Font::isFallbackValid() const { | 650 bool Font::isFallbackValid() const { |
| 1016 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 651 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
| 1017 } | 652 } |
| 1018 | 653 |
| 1019 } // namespace blink | 654 } // namespace blink |
| OLD | NEW |