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 |